package com.yanqu.road.server.gameplayer.module.activity.xiuxian;

import com.yanqu.road.entity.activity.ActivityInfo;
import com.yanqu.road.entity.activity.xiuxian.config.*;
import com.yanqu.road.entity.activity.xiuxian.data.*;
import com.yanqu.road.entity.config.goods.GoodsInfo;
import com.yanqu.road.entity.enums.*;
import com.yanqu.road.entity.enums.xiuxian.eXiuXianPvpActivityStateType;
import com.yanqu.road.entity.enums.xiuxian.eXiuXianType;
import com.yanqu.road.entity.log.*;
import com.yanqu.road.entity.messageSubscribe.entity.MessageUserNoticeData;
import com.yanqu.road.entity.task.args.XiuXianXianLiRankArgs;
import com.yanqu.road.logic.bussiness.activity.XiuXianActivityBusiness;
import com.yanqu.road.logic.helper.ActivityHelper;
import com.yanqu.road.logic.helper.CalcPowerResult;
import com.yanqu.road.logic.helper.PowerHelper;
import com.yanqu.road.logic.helper.RandomWeightConfigHelper;
import com.yanqu.road.logic.pb.CrossXiuXianPb;
import com.yanqu.road.message.YanQuMessage;
import com.yanqu.road.pb.activity.XiuXianProto;
import com.yanqu.road.server.GameServer;
import com.yanqu.road.server.gameplayer.GamePlayer;
import com.yanqu.road.server.gameplayer.module.base.GeneralModule;
import com.yanqu.road.server.gameplayer.module.player.CurrencyModule;
import com.yanqu.road.server.manger.activity.ActivityMgr;
import com.yanqu.road.server.manger.activity.xiuxian.XiuXianMgr;
import com.yanqu.road.server.manger.config.GoodsMgr;
import com.yanqu.road.server.manger.config.SystemOpenMgr;
import com.yanqu.road.server.manger.log.AutoLogMgr;
import com.yanqu.road.server.manger.messagesubscribe.MessageSubscribeMgr;
import com.yanqu.road.server.manger.player.GamePlayerMgr;
import com.yanqu.road.server.manger.player.UserMgr;
import com.yanqu.road.server.pb.PlayerPb;
import com.yanqu.road.server.pb.XiuXianPb;
import com.yanqu.road.server.protocol.ClientProtocol;
import com.yanqu.road.server.protocol.CrossProtocol;
import com.yanqu.road.server.protocol.GameErrorCode;
import com.yanqu.road.server.protocol.Protocol;
import com.yanqu.road.utils.RandomHelper;
import com.yanqu.road.utils.TimeHelper;
import com.yanqu.road.utils.YanQuMessageUtils;
import com.yanqu.road.utils.date.DateHelper;
import com.yanqu.road.utils.property.Property;
import com.yanqu.road.utils.property.PropertyHelper;
import com.yanqu.road.utils.string.StringUtils;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 凡人修仙
 */
public class XiuXianModule extends GeneralModule {

    private static String behaviorSeparatorStr = "-";   // 行为统计分隔符

    private RandomHelper randomHelper = new RandomHelper();

    private XiuXianUserData userData;

    private Map<String, XiuXianUserBehaviorData> behaviorMap = new ConcurrentHashMap<>();

    private Map<Integer, XiuXianMissionData> missionMap = new ConcurrentHashMap<>();

    private XiuXianBattleScene tempBattleScene;     // 战斗场景缓存

    public XiuXianModule(GamePlayer player) {
        super(player);
    }

    /**
     * 封装获取行为key
     */
    public String getBehaviorKey(int missionId, int behaviorType, int param) {

        return missionId + behaviorSeparatorStr + behaviorType + behaviorSeparatorStr + param;
    }
    /**
     * 通过key获取地图类型
     */
    public int getMissionIdByBehaviorKey(String behaviorKey) {
        String[] keyArray = behaviorKey.split(behaviorSeparatorStr);
        return Integer.parseInt(keyArray[0]);
    }

    @Override
    public boolean loadData() {
        XiuXianConfig config = XiuXianMgr.getConfig();
        if (config != null && ActivityMgr.activityInShowTime(config.getActivityInfo())) {
            // 加载用户数据
            userData = XiuXianActivityBusiness.getXiuXianUserData(config.getActivityInfo().getActivityId(), player.getUserId());
            // 加载玩家历练地图行为统计
            List<XiuXianUserBehaviorData> behaviorDataList = XiuXianActivityBusiness.getXiuXianUserBehaviorData(config.getActivityInfo().getActivityId(), player.getUserId());
            for(XiuXianUserBehaviorData behaviorData : behaviorDataList) {
                String key = getBehaviorKey(behaviorData.getMissionId(), behaviorData.getBehaviorType(), behaviorData.getBehaviorParam());
                behaviorMap.put(key, behaviorData);
            }
            // 地图数据
            missionMap = XiuXianActivityBusiness.getXiuXianMissionData(config.getActivityInfo().getActivityId(), player.getUserId());
        }
        return true;
    }

    /**
     * 初始化玩家数据
     */
    private synchronized void initUserData() {
        // 系统未解锁
        if (!SystemOpenMgr.systemOpen(player, eSystemId.XiuXian.getValue())) {
            return;
        }

        XiuXianConfig config = XiuXianMgr.getConfig();
        if (config != null && ActivityMgr.activityInShowTime(config.getActivityInfo())) {
            if (userData == null || config.getActivityInfo().getActivityId() != userData.getActivityId()) {
                XiuXianUserData xiuXianUserData = new XiuXianUserData();
                xiuXianUserData.setActivityId(config.getActivityInfo().getActivityId());
                xiuXianUserData.setUserId(player.getUserId());
                xiuXianUserData.setTripodLv(1);
                xiuXianUserData.setTripodEquipment(new XiuXianEquipmentData());
                xiuXianUserData.setPowerVal(0);
                xiuXianUserData.setAngerVal(0);
                xiuXianUserData.setPracticeVal(0);
                xiuXianUserData.setPracticeSpeed(0);
                xiuXianUserData.setBreakCount(0);
                xiuXianUserData.setEnergy(config.getXIUXIAN_ENERGY_INIT());
                xiuXianUserData.setLastBreakFailTime(0);
                xiuXianUserData.setLastEnergyRecTime(System.currentTimeMillis());
                xiuXianUserData.setLastMeditateTime(0);
                xiuXianUserData.setImageId(0);
                xiuXianUserData.setEnergyUseCount(0);
                xiuXianUserData.setTotalUseEnergy(0);
                xiuXianUserData.setPvpEndRound(0);
                xiuXianUserData.setStateId(config.getInitStateId());
                xiuXianUserData.setItems(new Property());
                xiuXianUserData.setInsertOption();
                userData = xiuXianUserData;

                // 清理数据
                missionMap.clear();
                behaviorMap.clear();
            }
        }
        if (config != null && ActivityMgr.activityInShowTime(config.getActivityInfo())) {
            if (userData != null) {
                if (userData.getSectId() == 0) {
                    // 2023年1月22日03:07:29 热更
                    // 去跨服拿下活动数据,判断下有没有结束了
                    XiuXianProto.CrossXiuXianGetActivityDataReqMsg.Builder builder = XiuXianProto.CrossXiuXianGetActivityDataReqMsg.newBuilder();
                    builder.setActivityId(XiuXianMgr.getConfig().getActivityInfo().getActivityId());
                    builder.setUserBaseInfo(PlayerPb.parsePlayerBaseTempMsg(player.getUserInfo()));
                    player.sendPacket(CrossProtocol.C_CROSS_XIU_XIAN_GET_ACTIVITY_DATA, builder);

                    // 登录同步到跨服、并且返回数据才下发给客户端
                    propertyChangeToCrossByLogin();
                } else {
                    syncUserData();
                }
            }
        }
    }

    @Override
    public boolean afterLoadData() {
        return true;
    }

    @Override
    public boolean saveData() {
        if (userData != null) {
            if (userData.isInsertOption()) {
                XiuXianActivityBusiness.addXiuXianUserData(userData);
            } else if (userData.isUpdateOption()) {
                XiuXianActivityBusiness.updateXiuXianUserData(userData);
            }
        }
        for (XiuXianUserBehaviorData data : behaviorMap.values()) {
            if (data.isInsertOption()) {
                XiuXianActivityBusiness.addXiuXianUserBehaviorData(data);
            } else if (data.isUpdateOption()) {
                XiuXianActivityBusiness.updateXiuXianBehaviorUserData(data);
            }
        }
        for (XiuXianMissionData data : missionMap.values()) {
            if (data.isInsertOption()) {
                XiuXianActivityBusiness.addXiuXianUserMissionData(data);
            } else if (data.isUpdateOption()) {
                XiuXianActivityBusiness.updateXiuXianMissionUserData(data);
            }
        }
        return true;
    }

    @Override
    public void afterLogin() {
        xiuXianLogin();
    }

    public XiuXianUserData getUserData() {
        return userData;
    }

    public void xiuXianLogin() {
        // 初始化
        initUserData();
        // 同步配置
        syncConfig();
        // 同步下pvp活动数据
        syncPvpActivityData();

        XiuXianConfig config = XiuXianMgr.getConfig();
        //  活动进行时间和领奖期间才更新
        if (config != null && ActivityMgr.activityInTimeAndShowTime(config.getActivityInfo())) {
            // 凡人修仙传宗门使用药草总数量
            player.notifyListener(eGamePlayerEventType.XiuXianSectUseEnergyCount.getValue(), BigInteger.valueOf(XiuXianMgr.getSectTotalEnergy()));
        }

        // 设置微信推送时间
        try {
            MessageSubscribePushTime();
        }catch (Exception e){
            log.error("error:" + e);
        }
    }

    public void syncPvpActivityData() {
        if (userData == null || null == XiuXianMgr.getConfig()) {
            return;
        }
        // 去跨服拿下活动数据,判断下有没有结束了
        XiuXianProto.CrossXiuXianGetActivityDataReqMsg.Builder builder = XiuXianProto.CrossXiuXianGetActivityDataReqMsg.newBuilder();
        builder.setActivityId(XiuXianMgr.getConfig().getActivityInfo().getActivityId());
        builder.setUserBaseInfo(PlayerPb.parsePlayerBaseTempMsg(player.getUserInfo()));
        player.sendPacket(CrossProtocol.C_CROSS_XIU_XIAN_GET_ACTIVITY_DATA, builder);
    }

    public void syncPvpActivityDataFromCross(XiuXianProto.CrossXiuXianPvpActivityDataSync crossXiuXianPvpActivityDataSync) {
        if (userData == null) {
            return;
        }
        // pvp没开启不处理
        if (!pvpOpen()) {
            return;
        }
        XiuXianProto.XiuXianPvpActivityDataSync.Builder builder = XiuXianProto.XiuXianPvpActivityDataSync.newBuilder();
        // 当前轮次
        int round = crossXiuXianPvpActivityDataSync.getRound();
        // 活动状态
        int state = crossXiuXianPvpActivityDataSync.getState();
        XiuXianProto.XiuXianPvpActivityDataTemp.Builder activity = XiuXianProto.XiuXianPvpActivityDataTemp.newBuilder();
        int pvpEndRound = userData.getPvpEndRound();
        activity.setEndRound(pvpEndRound);
        // 当前可展示轮次
        int showRound = state == eXiuXianPvpActivityStateType.End.getValue() ? round : round - 1;
        activity.setShowEnd(showRound > pvpEndRound);
        builder.setActivityData(activity);
        player.sendPacket(ClientProtocol.U_XIU_XIAN_GET_ACTIVITY_DATA, builder);
    }

    /**
     * 设置推送时间
     */
    private void MessageSubscribePushTime(){
        if(!MessageSubscribeMgr.isSwitch()){
            return;
        }
        if (XiuXianMgr.getConfig() == null) {
            return;
        }
        ActivityInfo xiuXianAct = XiuXianMgr.getConfig().getActivityInfo();
        if (xiuXianAct == null) {
            return;
        }
        List<Long> timeList = new ArrayList<>();
        long beginTime = DateHelper.getZeroTimeStamp(xiuXianAct.getBeginTime() * 1000) / 1000;
        long endTime = DateHelper.getZeroTimeStamp((xiuXianAct.getEndTime() - XiuXianMgr.getConfig().getPvpPrepareTimeList().get(0) - XiuXianMgr.getConfig().getPvpPrepareTimeList().get(1) - XiuXianMgr.getConfig().getPvpBattleTimeEndCondition().get(0)) * 1000) / 1000;
        for (int i = 0; i <= (endTime - beginTime) / DateHelper.DAY_SECONDS; i++){
            long battleTime = DateHelper.getZeroTimeStamp((beginTime + i * DateHelper.DAY_SECONDS) * DateHelper.SECOND_MILLIONS) + (XiuXianMgr.getConfig().getPvpPrepareTimeList().get(0) + XiuXianMgr.getConfig().getPvpPrepareTimeList().get(1)) * DateHelper.SECOND_MILLIONS - 5 * 60 * DateHelper.SECOND_MILLIONS;
            if (battleTime <= 0) {
                continue;
            }
            timeList.add(battleTime);
        }
        MessageUserNoticeData noticeData = MessageSubscribeMgr.getUserNoticeData(player.getUserId());
        noticeData.setSubTime(eMessageSubscribeType.XiuXianTime, timeList);
    }

    /**
     * 同步配置
     */
    public void syncConfig() {
        XiuXianConfig config = XiuXianMgr.getConfig();
        if (config != null && ActivityMgr.activityInShowTime(config.getActivityInfo())) {
            XiuXianProto.XiuXianConfigSyncMsg.Builder builder = XiuXianPb.parseXiuXianConfigSyncMsg(config, player.getUserInfo().getLanguage());
            player.sendPacket(ClientProtocol.U_XIU_XIAN_CONFIG_SYNC, builder);
        }
    }
    /**
     * 同步玩家数据-跨服返回
     **/
    public void syncUserDataFromCross(XiuXianProto.XiuXianSyncLoginDataRespMsg crossLoginMsg){
        XiuXianConfig config = XiuXianMgr.getConfig();
        if (config != null && ActivityMgr.activityInShowTime(config.getActivityInfo())) {
            if(null == userData){
                return;
            }
            // 阵营id
            int campId = crossLoginMsg.getCampId();
            userData.setSectId(campId);
            syncUserData();
        }
    }
    /**
     * 同步玩家数据
     **/
    public void syncUserData(){
        XiuXianConfig config = XiuXianMgr.getConfig();
        if (config != null && ActivityMgr.activityInShowTime(config.getActivityInfo())) {
            if(null == userData){
                return;
            }
            // 恢复体力
            recoveryEnergy();
            XiuXianProto.XiuXianUserDataSync.Builder dataMsg = XiuXianProto.XiuXianUserDataSync.newBuilder();
            XiuXianProto.XiuXianUserDataTemp.Builder parseUserData = XiuXianPb.parseUserData(userData, behaviorMap, missionMap);
            if (parseUserData != null) {
                dataMsg.setUserData(parseUserData);
                player.sendPacket(Protocol.U_XIU_XIAN_USER_DATA_SYNC, dataMsg);
            }
        }
    }

    /**
     * pvp开启且在活动时间内
     */
    public boolean pvpOpen() {
        XiuXianConfig config = XiuXianMgr.getConfig();
        if (config == null) {
            return false;
        }
        if (userData == null) {
            return false;
        }
        if (config.getXIUXIAN_PVP_IS_OPEN() == 0) {
            return false;
        }
        // 具体是否在斗法时间内，上跨服去判断
        return true;
    }

    /**
     * 进入pvp
     */
    public int enterPvp() {
        if (!pvpOpen()) {
            return GameErrorCode.E_XIU_XIAN_PVP_NOT_OPEN;
        }
        // 发到跨服拿数据
        XiuXianProto.CrossXiuXianEnterPvpReqMsg.Builder builder = XiuXianProto.CrossXiuXianEnterPvpReqMsg.newBuilder();
        builder.setActivityId(XiuXianMgr.getConfig().getActivityInfo().getActivityId());
        player.sendPacket(CrossProtocol.C_CROSS_XIU_XIAN_ENTER_PVP, builder);
        return 0;
    }

    /**
     * 离开pvp
     */
    public int leavePvp() {
        if (!pvpOpen()) {
            return GameErrorCode.E_XIU_XIAN_PVP_NOT_OPEN;
        }
        // 发到跨服拿数据
        XiuXianProto.CrossXiuXianLeavePvpReqMsg.Builder builder = XiuXianProto.CrossXiuXianLeavePvpReqMsg.newBuilder();
        builder.setActivityId(XiuXianMgr.getConfig().getActivityInfo().getActivityId());
        player.sendPacket(CrossProtocol.C_CROSS_XIU_XIAN_LEAVE_PVP, builder);
        return 0;
    }

    /**
     * 进入房间
     * @param placeId 房间id
     */
    public int enterPlace(int placeId) {
        if (!pvpOpen()) {
            return GameErrorCode.E_XIU_XIAN_PVP_NOT_OPEN;
        }
        // 发到跨服拿数据
        XiuXianProto.CrossXiuXianEnterPlaceReqMsg.Builder builder = XiuXianProto.CrossXiuXianEnterPlaceReqMsg.newBuilder();
        builder.setActivityId(XiuXianMgr.getConfig().getActivityInfo().getActivityId());
        builder.setPlaceId(placeId);
        player.sendPacket(CrossProtocol.C_CROSS_XIU_XIAN_ENTER_PLACE, builder);
        return 0;
    }

    /**
     * 离开房间
     */
    public int leavePlace() {
        if (!pvpOpen()) {
            return GameErrorCode.E_XIU_XIAN_PVP_NOT_OPEN;
        }
        // 发到跨服拿数据
        XiuXianProto.CrossXiuXianLeavePlaceReqMsg.Builder builder = XiuXianProto.CrossXiuXianLeavePlaceReqMsg.newBuilder();
        builder.setActivityId(XiuXianMgr.getConfig().getActivityInfo().getActivityId());
        player.sendPacket(CrossProtocol.C_CROSS_XIU_XIAN_LEAVE_PLACE, builder);
        return 0;
    }

    /**
     * 移动
     */
    public int move(XiuXianProto.XiuXianPvpPositionTemp positionTemp) {
        if (!pvpOpen()) {
            return GameErrorCode.E_XIU_XIAN_PVP_NOT_OPEN;
        }
        // 发到跨服拿数据
        XiuXianProto.CrossXiuXianMoveReqMsg.Builder builder = XiuXianProto.CrossXiuXianMoveReqMsg.newBuilder();
        builder.setActivityId(XiuXianMgr.getConfig().getActivityInfo().getActivityId());
        builder.setPosition(positionTemp);
        player.sendPacket(CrossProtocol.C_CROSS_XIU_XIAN_MOVE, builder);
        return 0;
    }

    /**
     * 获取宗门积分记录
     */
    public int getCampScoreRecord(int campId) {
        // 发到跨服拿数据
        XiuXianProto.CrossXiuXianGetCampScoreRecordReqMsg.Builder builder = XiuXianProto.CrossXiuXianGetCampScoreRecordReqMsg.newBuilder();
        builder.setActivityId(XiuXianMgr.getConfig().getActivityInfo().getActivityId());
        builder.setCampId(campId);
        player.sendPacket(CrossProtocol.C_CROSS_XIU_XIAN_GET_CAMP_SCORE_RECORD, builder);
        return 0;
    }

    /**
     * 攻击pvp目标
     */
    public int pvpAttack(long attackUserId) {
        if (!pvpOpen()) {
            return GameErrorCode.E_XIU_XIAN_PVP_NOT_OPEN;
        }
        // 发到跨服拿数据
        XiuXianProto.CrossXiuXianAttackReqMsg.Builder builder = XiuXianProto.CrossXiuXianAttackReqMsg.newBuilder();
        builder.setActivityId(XiuXianMgr.getConfig().getActivityInfo().getActivityId());
        builder.setAttackUserId(attackUserId);
        player.sendPacket(CrossProtocol.C_CROSS_XIU_XIAN_ATTACK, builder);
        return 0;
    }

    /**
     * 攻击pvp目标
     */
    public int appointMinorUser(long minorUserId) {
        if (!pvpOpen()) {
            return GameErrorCode.E_XIU_XIAN_PVP_NOT_OPEN;
        }
        // 发到跨服拿数据
        XiuXianProto.CrossAppointMinorUserReqMsg.Builder builder = XiuXianProto.CrossAppointMinorUserReqMsg.newBuilder();
        builder.setActivityId(XiuXianMgr.getConfig().getActivityInfo().getActivityId());
        builder.setMinorUserId(minorUserId);
        player.sendPacket(CrossProtocol.C_CROSS_XIU_XIAN_APPOINT_MINOR_USER, builder);
        return 0;
    }

    /**
     * 标记地点
     */
    public int markPlace(int placeId) {
        if (!pvpOpen()) {
            return GameErrorCode.E_XIU_XIAN_PVP_NOT_OPEN;
        }
        // 发到跨服拿数据
        XiuXianProto.CrossMarkPlaceReqMsg.Builder builder = XiuXianProto.CrossMarkPlaceReqMsg.newBuilder();
        builder.setActivityId(XiuXianMgr.getConfig().getActivityInfo().getActivityId());
        builder.setPlaceId(placeId);
        player.sendPacket(CrossProtocol.C_CROSS_XIU_XIAN_MARK_PLACE, builder);
        return 0;
    }

    public int getMaxAbilityUser() {
        if (!pvpOpen()) {
            return GameErrorCode.E_XIU_XIAN_PVP_NOT_OPEN;
        }
        // 发到跨服拿数据
        XiuXianProto.CrossXiuXianGetMajorUserReqMsg.Builder builder = XiuXianProto.CrossXiuXianGetMajorUserReqMsg.newBuilder();
        builder.setActivityId(XiuXianMgr.getConfig().getActivityInfo().getActivityId());
        player.sendPacket(CrossProtocol.C_CROSS_XIU_XIAN_GET_MAJOR_USER, builder);
        return 0;
    }

    /**
     * 获取阵营服务器
     */
    public int getCampServer() {
        if (!pvpOpen()) {
            return GameErrorCode.E_XIU_XIAN_PVP_NOT_OPEN;
        }
        // 发到跨服拿数据
        XiuXianProto.CrossXiuXianGetCampServerReqMsg.Builder builder = XiuXianProto.CrossXiuXianGetCampServerReqMsg.newBuilder();
        builder.setActivityId(XiuXianMgr.getConfig().getActivityInfo().getActivityId());
        player.sendPacket(CrossProtocol.C_CROSS_XIU_XIAN_GET_CAMP_SERVER, builder);
        return 0;
    }

    /**
     * 获取阵营成员信息列表
     */
    public int getCampUserList() {
        if (!pvpOpen()) {
            return GameErrorCode.E_XIU_XIAN_PVP_NOT_OPEN;
        }
        // 发到跨服拿数据
        XiuXianProto.CrossXiuXianGetCampUserListReqMsg.Builder builder = XiuXianProto.CrossXiuXianGetCampUserListReqMsg.newBuilder();
        builder.setActivityId(XiuXianMgr.getConfig().getActivityInfo().getActivityId());
        player.sendPacket(CrossProtocol.C_CROSS_XIU_XIAN_GET_CAMP_USER_LIST, builder);
        return 0;
    }

    /**
     * 获取房间信息
     */
    public int getPlaceInfo() {
        if (!pvpOpen()) {
            return GameErrorCode.E_XIU_XIAN_PVP_NOT_OPEN;
        }
        // 发到跨服拿数据
        XiuXianProto.CrossXiuXianGetPlaceInfoReqMsg.Builder builder = XiuXianProto.CrossXiuXianGetPlaceInfoReqMsg.newBuilder();
        builder.setActivityId(XiuXianMgr.getConfig().getActivityInfo().getActivityId());
        player.sendPacket(CrossProtocol.C_CROSS_XIU_XIAN_GET_PLACE_INFO, builder);
        return 0;
    }

    public int getPvpEndData() {
        if (!pvpOpen()) {
            return GameErrorCode.E_XIU_XIAN_PVP_NOT_OPEN;
        }
        // 发到跨服拿数据
        XiuXianProto.CrossXiuXianGetPvpEndDataReqMsg.Builder builder = XiuXianProto.CrossXiuXianGetPvpEndDataReqMsg.newBuilder();
        builder.setActivityId(XiuXianMgr.getConfig().getActivityInfo().getActivityId());
        builder.setEndRound(userData.getPvpEndRound());
        player.sendPacket(CrossProtocol.C_CROSS_XIU_XIAN_GET_PVP_END_DATA, builder);
        return 0;
    }

    /**
     * 获取PVP战报
     */
    public int getPvpReport(long targetUserId) {
        if (!pvpOpen()) {
            return GameErrorCode.E_XIU_XIAN_PVP_NOT_OPEN;
        }
        // 发到跨服拿数据
        XiuXianProto.CrossXiuXianGetPvpReportReqMsg.Builder builder = XiuXianProto.CrossXiuXianGetPvpReportReqMsg.newBuilder();
        builder.setActivityId(XiuXianMgr.getConfig().getActivityInfo().getActivityId());
        builder.setUserId(targetUserId);
        player.sendPacket(CrossProtocol.C_CROSS_XIU_XIAN_GET_PVP_REPORT, builder);
        return 0;
    }

    /**
     * 属性变化需上传用户数据到跨服
     */
    public void propertyChangeToCross() {
        buildPropertyChangeToCross(false);
    }

    /**
     * 属性变化需上传用户数据到跨服-登录
     */
    public void propertyChangeToCrossByLogin() {
        buildPropertyChangeToCross(true);
    }
    /**
     * 属性变化需上传用户数据到跨服-登录
     */
    private void buildPropertyChangeToCross(boolean isLoginSync) {
        XiuXianConfig config = XiuXianMgr.getConfig();
        if (config == null || !ActivityMgr.activityInShowTime(config.getActivityInfo())) {
            return;
        }
        if (userData == null) {
            return;
        }
        XiuXianProto.CrossXiuXianPvePropertyChangeReqMsg.Builder builder = XiuXianProto.CrossXiuXianPvePropertyChangeReqMsg.newBuilder();
        builder.setActivityId(config.getActivityInfo().getActivityId());
        builder.setUserId(player.getUserId());
        builder.setServerId(GameServer.getInstance().getServerId());
        builder.setIsLoginSync(isLoginSync);
        builder.setPveProperty(XiuXianPb.parseXiuXianPveUserPropertyTemp(userData));
        player.sendPacket(CrossProtocol.C_CROSS_XIU_XIAN_PVE_PROPERTY_CHANGE, builder);
    }

    /**
     * 自然恢复体力逻辑
     */
    public void recoveryEnergy(){
        // 获取活动配置
        XiuXianConfig config = XiuXianMgr.getConfig();
        if(userData != null && config != null){
            int logBeforeEnergy = userData.getEnergy();

            // 计算
            CalcPowerResult result = PowerHelper.calcPower(
                    userData.getLastEnergyRecTime() / 1000,
                    config.getXIUXIAN_ENERGY_CD(),
                    config.getXIUXIAN_ENERGY_CD_NUM(),
                    config.getXIUXIAN_ENERGY_INIT(),
                    userData.getEnergy()
            );
            // 更新内存
            userData.setEnergy(result.getCurPower());
            userData.setLastEnergyRecTime(result.getLastRecoverTime() * 1000);
            // 体力日志
            if (userData.getEnergy() != logBeforeEnergy) {
                AutoLogMgr.add(new LogXiuXianEnergy(userData.getUserId(), userData.getActivityId(), 3, userData.getEnergy() - logBeforeEnergy, userData.getEnergy()));
            }
        }
    }

    /**
     * 检测活动数据
     */
    private int checkActivityData(int activityId) {
        // 没有玩家活动数据
        if(userData == null){
            return GameErrorCode.E_ACTIVITY_OVER_TIME;
        }
        // 没有活动配置
        XiuXianConfig config = XiuXianMgr.getConfig();
        if(config == null){
            return GameErrorCode.E_ACTIVITY_OVER_TIME;
        }
        // 活动是否同一个、是否在活动中
        ActivityInfo activityInfo = config.getActivityInfo();
        if(activityInfo == null || activityId != activityInfo.getActivityId()
                || !ActivityHelper.activityInTime(activityInfo)) {
            return GameErrorCode.E_ACTIVITY_OVER_TIME;
        }
        return 0;
    }

    /**
     * 设置形象
     */
    public int imageSet(int activityId, int imageId) {
        // 检测活动参数
        int checkRet = checkActivityData(activityId);
        if (checkRet != 0) {
            return checkRet;
        }
        if (userData.getImageId() > 0) {
            // 已经设置过了
            return GameErrorCode.E_XIU_XIAN_IMAGE_HAS_SET;
        }
        // 更新内存
        userData.setImageId(imageId);

        // 上传到跨服
        propertyChangeToCross();

        // 返回给客户端
        XiuXianProto.XiuXianSetImageRespMsg.Builder builder = XiuXianProto.XiuXianSetImageRespMsg.newBuilder();
        builder.setRet(0);
        player.sendPacket(Protocol.U_XIU_XIAN_SET_IMAGE, builder);
        return 0;
    }

    /**
     * 凡人pve开始打坐
     */
    public int startMeditate(int activityId) {
        // 检测活动参数
        int checkRet = checkActivityData(activityId);
        if (checkRet != 0) {
            return checkRet;
        }
        // 设置开始打坐时间 更新内存数据
        if (userData.getLastMeditateTime() == 0) {
            userData.setLastMeditateTime(System.currentTimeMillis()/1000);
        }
        calcPracticeSpeedNew();

        // 返回客户端 兼容重复请求
        XiuXianProto.XiuXianStartMeditateRespMsg.Builder builder = XiuXianProto.XiuXianStartMeditateRespMsg.newBuilder();
        builder.setRet(0);
        builder.setLastMeditateTime(userData.getLastMeditateTime());
        builder.setPracticeSpeed(userData.getPracticeSpeed());
        builder.setPracticeVal(userData.getPracticeVal());
        player.sendPacket(Protocol.U_XIU_XIAN_START_MEDITATE, builder);
        return 0;
    }

    /**
     * 使用体力道具恢复体力接口
     */
    public int useEnergyItem(int activityId, int count) {
        if (count <= 0 || count > 9999) {
            return GameErrorCode.E_XIU_XIAN_ACTIVITY_USE_COUNT_ERROR;
        }
        int checkRet = checkActivityData(activityId);
        if(checkRet != 0) {
            return checkRet;
        }

        XiuXianConfig config = XiuXianMgr.getConfig();
        Property cost = new Property();
        cost.addProperty(config.getXIUXIAN_ENERGY_RECOVERY_ITEM_ID(), BigInteger.valueOf(count));

        // 检测道具是否足够
        if(!player.getModule(CurrencyModule.class).currencyIsEnough(cost)) {
            return GameErrorCode.E_BAG_ITEM_NO_ENOUGH;
        }

        // 计算恢复数量
        GoodsInfo goodsInfo = GoodsMgr.getGoodsById(config.getXIUXIAN_ENERGY_RECOVERY_ITEM_ID());
        BigInteger energyCount = goodsInfo.getParamList().get(0);
        int totalCount = energyCount.intValue() * count;

        // 扣道具
        if (!player.getModule(CurrencyModule.class).removeCurrency(cost, eLogMoneyType.XiuXianActivity, eLogMoneyType.XiuXianActivityEnergyItemConsume)) {
            return GameErrorCode.E_BAG_ITEM_NO_ENOUGH;
        }

        // 恢复体力
        recoveryEnergy();

        // 加体力
        userData.setEnergy(userData.getEnergy() + totalCount);
        if (userData.getEnergy() >= config.getXIUXIAN_ENERGY_LIMIT()) {
            userData.setLastEnergyRecTime(System.currentTimeMillis());
        }
        // 返回给客户端
        XiuXianProto.XiuXianUseEnergyItemRespMsg.Builder builder = XiuXianProto.XiuXianUseEnergyItemRespMsg.newBuilder();
        builder.setRet(0);
        builder.setEnergy(userData.getEnergy());
        builder.setLastEnergyRecTime(userData.getLastEnergyRecTime());
        player.sendPacket(Protocol.U_XIU_XIAN_USE_ENERGY_ITEM, builder);

        //体力日志
        AutoLogMgr.add(new LogXiuXianEnergy(userData.getUserId(), userData.getActivityId(), 2, totalCount, userData.getEnergy()));
        return 0;
    }
    /**
     * 更新仙力
     **/
    public void updatePowerVal(long newPowerVal) {
        if (newPowerVal != userData.getPowerVal()) {
            userData.setPowerVal(newPowerVal);
            if (userData.getMaxPowerVal() < userData.getPowerVal()) {
                userData.setMaxPowerVal(userData.getPowerVal());
                // 玩家最高仙力变更事件成就通知
                player.notifyListener(eGamePlayerEventType.XiuXianXianLi.getValue(), BigInteger.valueOf(userData.getMaxPowerVal()));
                // 玩家最高变更事件榜单通知
                XiuXianXianLiRankArgs rankArgs = new XiuXianXianLiRankArgs(userData.getStateId(), userData.getMaxPowerVal());
                player.notifyListener(eGamePlayerEventType.XiuXianXianLiRank.getValue(), rankArgs);
            }
            // 同步给客户端
            syncPveChangeData();
        }
        // 上传到跨服
        propertyChangeToCross();
    }
    /**
     * 计算修为产速逻辑新的
     **/
    public long calcPracticeSpeedNew() {
        if (userData.getLastMeditateTime() == 0) {
            return 0;
        }
        XiuXianConfig config = XiuXianMgr.getConfig();
        long nowTime = System.currentTimeMillis()/1000;
        // 结算时间
        long tempLastMeditateTime = userData.getLastMeditateTime();
        long addPracticeVal = 0L;

        XiuXianStateConfig stateConfig = XiuXianMgr.getConfig().getStateConfigMap().get(userData.getStateId());
        XiuXianUserMountAllotData userMountAllotData = XiuXianMgr.getUserMountData(userData.getUserId());
        int curPracticeSpeed = userData.getPracticeSpeed();
        int curMountId = userData.getMountId();
        for (long calTime = XiuXianMgr.getHistoryAllotTime(userData.getLastMeditateTime()); calTime < nowTime; calTime = calTime + config.getXIUXIAN_PEAK_ASSIGN_CD()) {
            int peakId = 0;
            // TODO 找不到对应的灵峰，容错处理，以上一次的灵峰进行结算
            if (userMountAllotData == null || !userMountAllotData.getUserMountMap().containsKey(calTime)) {
                peakId = curMountId;
            } else {
                peakId = userMountAllotData.getUserMountMap().get(calTime).getMountId();
            }
            if (peakId == 0) {
                // 实在找不到兼容用默认灵峰
                peakId = config.getDefaultMount();
            }
            XiuXianPeakConfig peakConfig = config.getPeakConfigMap().get(peakId);
            curPracticeSpeed = detailCalcPracticeSpeed(stateConfig, peakConfig);
            curMountId = peakId;

            long addTime = calTime + config.getXIUXIAN_PEAK_ASSIGN_CD() - tempLastMeditateTime;
            if (calTime < tempLastMeditateTime) {
                // 首次不足
                addTime = calTime + config.getXIUXIAN_PEAK_ASSIGN_CD() - tempLastMeditateTime;
            }
            if (calTime + config.getXIUXIAN_PEAK_ASSIGN_CD() > nowTime) {
                // 最后一次
                addTime = nowTime - tempLastMeditateTime;
            }
            long tempSettleCount = addTime /config.getXIUXIAN_STATE_PRODUCTION_XIUWEI_CD();
            addPracticeVal += curPracticeSpeed * tempSettleCount;
            tempLastMeditateTime += tempSettleCount * config.getXIUXIAN_STATE_PRODUCTION_XIUWEI_CD();
        }
        // 更新内存
        userData.setPracticeSpeed(curPracticeSpeed);
        userData.setMountId(curMountId);
        userData.setPracticeVal(userData.getPracticeVal() + addPracticeVal);
        userData.setLastMeditateTime(tempLastMeditateTime);
        if (addPracticeVal > 0) {
            // 同步属性变化
            syncPveChangeData();

            // 修为日志
            AutoLogMgr.add(new LogXiuXianPracticeVal(userData.getUserId(), userData.getActivityId(), userData.getStateId(), 2, addPracticeVal, userData.getPracticeVal(), 0));
        }
        return addPracticeVal;
    }
    /**
     *  修为公式  玩家境界基础产速*（1+宗门加成）
     */
    private int detailCalcPracticeSpeed(XiuXianStateConfig stateConfig, XiuXianPeakConfig peakConfig) {
        int tempPracticeSpeed = (int)Math.ceil(stateConfig.getPracticeSpeed() * (1 + (double)peakConfig.getAttributeAdd() / 1000));
        return tempPracticeSpeed;
    }

    /**
     * 同步pve变更的属性
     **/
    public void syncPveChangeData() {
        XiuXianProto.XiuXianPveChangeDataSync.Builder builder = XiuXianProto.XiuXianPveChangeDataSync.newBuilder();
        builder.setChangeData(XiuXianPb.parsePveChangeDataTemp(userData));
        player.sendPacket(Protocol.U_XIU_XIAN_PVE_CHANGE_DATA_SYNC, builder);
    }

    /**
     * 同步灵峰房间操作
     **/
    public void syncMountRoomOpToCross(int activityId, int opType, int opArg) {
        XiuXianProto.CrossXiuXianRoomMemberOpReqMsg.Builder builder = XiuXianProto.CrossXiuXianRoomMemberOpReqMsg.newBuilder();
        builder.setActivityId(activityId);
        builder.setOpType(opType);
        builder.setOpArg(opArg);
        player.sendPacket(Protocol.C_CROSS_XIU_XIAN_ROOM_MEMBER_OP, builder);
    }

    /**
     * 获取pve变更数据
     **/
    public int getPveChangeDataByCmd(int activityId) {
        // 检测活动相关数据
        int checkRet = checkActivityData(activityId);
        if(checkRet != 0) {
            return checkRet;
        }
        // 计算修为
        calcPracticeSpeedNew();

        XiuXianProto.XiuXianGetPveChangeDataRespMsg.Builder builder = XiuXianProto.XiuXianGetPveChangeDataRespMsg.newBuilder();
        builder.setRet(0);
        builder.setChangeData(XiuXianPb.parsePveChangeDataTemp(userData));
        player.sendPacket(Protocol.U_XIU_XIAN_GET_PVE_CHANGE_DATA, builder);
        return 0;
    }

    /**
     * 获取用户数据-这里是触发-返回走同步协议
     **/
    public int getUserDataByCmd(int activityId) {
        // 检测活动相关数据
        int checkRet = checkActivityData(activityId);
        if(checkRet != 0) {
            return checkRet;
        }
        // 初始化并同步
        initUserData();
        return 0;
    }

    /**
     * 使用体力
     */
    public int useEnergy(int activityId, int count) {
        if (count <= 0) {
            return GameErrorCode.E_XIU_XIAN_ACTIVITY_USE_COUNT_ERROR;
        }
        // 检测活动相关数据
        int checkRet = checkActivityData(activityId);
        if(checkRet != 0) {
            return checkRet;
        }
        XiuXianConfig config = XiuXianMgr.getConfig();

        // 恢复体力
        recoveryEnergy();
        // 使用次数大于当前体力时取当前体力最大值
        count = Math.min(count, userData.getEnergy());
        // 体力是否足够
        if (count <= 0 || userData.getEnergy() < count) {
            return GameErrorCode.E_XIU_XIAN_ACTIVITY_USE_ENERGY_LIMIT;
        }

        // 修为结算
        calcPracticeSpeedNew();

        // 扣除体力
        userData.setEnergy(userData.getEnergy() - count);       // 更新体力
        userData.setEnergyUseCount(userData.getEnergyUseCount() + count);     // 更新体力使用次数

        // 转化为机缘点
        int addLuckPoint = 0;
        if (userData.getEnergyUseCount() >= config.getXIUXIAN_ENERGY_COST()) {
            // 随机机缘点数量
            int remainEnergyUseCount = userData.getEnergyUseCount() % config.getXIUXIAN_ENERGY_COST();
            for (int i = 0; i < userData.getEnergyUseCount() / config.getXIUXIAN_ENERGY_COST(); i++) {
                addLuckPoint += RandomHelper.getRandomKeyByWeight(config.getXIUXIAN_ENERGY_OBTAIN1());
            }
            userData.setEnergyUseCount(remainEnergyUseCount);
        }

        // 更新使用体力总数量
        userData.setTotalUseEnergy(userData.getTotalUseEnergy() + count);
        userData.setLuckPoint(userData.getLuckPoint() + addLuckPoint);

        // 获得修为值=体力数量*境界基础产速*系数
        XiuXianStateConfig stateConfig = XiuXianMgr.getConfig().getStateConfigMap().get(userData.getStateId());
        int addPracticeValue = count * stateConfig.getPracticeSpeed() * config.getXIUXIAN_ENERGY_OBTAIN2();
        userData.setPracticeVal(userData.getPracticeVal() + addPracticeValue);

        // 上传到跨服
        XiuXianProto.CrossXiuXianUseEnergyReqMsg.Builder crossReqMsg = XiuXianProto.CrossXiuXianUseEnergyReqMsg.newBuilder();
        crossReqMsg.setActivityId(activityId);
        crossReqMsg.setTotalUseEnergy(userData.getTotalUseEnergy());
        player.sendPacket(Protocol.C_CROSS_XIU_XIAN_USE_ENERGY_SYNC, crossReqMsg);

        // 每10次同步一次到灵峰房间
        if (userData.getTotalUseEnergy() % 10 == 1) {
            syncMountRoomOpToCross(activityId, eXiuXianType.RoomOpType.UseEnergy.getValue(), userData.getPracticeSpeed());
        }

        // 返回给客户端
        XiuXianProto.XiuXianUseEnergyRespMsg.Builder builder = XiuXianProto.XiuXianUseEnergyRespMsg.newBuilder();
        builder.setRet(0);
        builder.setEnergy(userData.getEnergy());
        builder.setLastEnergyRecTime(userData.getLastEnergyRecTime());
        builder.setPracticeVal(userData.getPracticeVal());
        builder.setAddLuckPoint(addLuckPoint);
        builder.setLuckPoint(userData.getLuckPoint());
        player.sendPacket(Protocol.U_XIU_XIAN_ENERGY_USE, builder);
        // 体力日志
        AutoLogMgr.add(new LogXiuXianEnergy(userData.getUserId(), userData.getActivityId(), 1, -count, userData.getEnergy()));
        // 机缘点日志
        AutoLogMgr.add(new LogXiuXianLuckPoint(userData.getUserId(), userData.getActivityId(), 1, addLuckPoint, userData.getLuckPoint()));
        // 修为日志
        AutoLogMgr.add(new LogXiuXianPracticeVal(userData.getUserId(), userData.getActivityId(), userData.getStateId(), 1, addPracticeValue, userData.getPracticeVal(), count));
        return 0;
    }

    /**
     * 领取机缘点 需求砍掉了，直接给机缘点，不需要领取操作
     */
    public int getLuckPoint(int activityId, int count) {
        return GameErrorCode.E_XIU_XIAN_PARAM_ERROR;
    }

    /**
     * 凡人境界突破/渡劫
     * 升级已当前等级为升级条件，如1级升2级，读1级的条件进行升级
     */
    public int stateUpgrade(int activityId) {
        // 检测活动参数
        int checkRet = checkActivityData(activityId);
        if(checkRet != 0) {
            return checkRet;
        }
        XiuXianConfig config = XiuXianMgr.getConfig();

        // 获取下一级境界
        Set<Integer> stateIdSet = config.getStateConfigMap().keySet();
        int nextStateId = 0;
        for (Integer value: stateIdSet) {
            if ((nextStateId == 0 && value > userData.getStateId()) || (value > userData.getStateId() && value < nextStateId)) {
                nextStateId = value;
            }
        }
        if (nextStateId == 0) {
            return GameErrorCode.E_XIU_XIAN_UPGRADE_LIMIT;
        }
        XiuXianStateConfig curStateConfig = config.getStateConfigMap().get(userData.getStateId());
        XiuXianStateConfig nextStateConfig = config.getStateConfigMap().get(nextStateId);
        // 是否是渡劫升级
        boolean isBreakUpgrade = true;
        if (curStateConfig.getStateType() == nextStateConfig.getStateType()) {
            isBreakUpgrade = false;
        }

        // 结算修为值
        calcPracticeSpeedNew();

        // 检测修为值否达到满足
        String[] needItemArray = curStateConfig.getNeedItem().split("=");
        if (needItemArray.length != 2) {
            return GameErrorCode.E_XIU_XIAN_CFG_ERROR;
        }
        long needPracticeVal = Long.valueOf(needItemArray[1]);
        if (userData.getPracticeVal() < needPracticeVal) {
            return GameErrorCode.E_XIU_XIAN_STATE_PRACTICE_LIMIT;
        }

        Property checkProperty = PropertyHelper.parseStringToProperty(curStateConfig.getConsumeItem());
        if (checkProperty == null) {
            return GameErrorCode.E_XIU_XIAN_CFG_ERROR;
        }
        if (!checkItemEnough(userData, checkProperty)) {
            return GameErrorCode.E_BAG_ITEM_NO_ENOUGH;
        }
        long curTimeSec = TimeHelper.getSysCurSeconds();
        boolean isSuccess = true;
        if (isBreakUpgrade) {
            // 是否渡劫成功
            isSuccess = isCanBreakSuccess(curStateConfig);
        }
        int oldStateId = userData.getStateId();
        long oldPowerVal = userData.getPowerVal();

        // 扣除的修为值
        long subPractice = needPracticeVal;
        if (isSuccess) {
            userData.setStateId(nextStateId);
            // 计算修为
            calcPracticeSpeedNew();
            // 法宝基础属性
            calcBattleProperty();
            // 重置渡劫失败进度
            userData.setBreakCount(0);
            // 玩家境界变更事件通知
            player.notifyListener(eGamePlayerEventType.XiuXianState.getValue(),userData.getStateId());
            // 玩家最高变更事件榜单通知
            XiuXianXianLiRankArgs rankArgs = new XiuXianXianLiRankArgs(userData.getStateId(), userData.getMaxPowerVal());

            // 计算虚空鼎替换后的仙力
            if (userData.getTripodEquipment().getEquipmentId() > 0) {
                Map<Integer, XiuXianEquipmentData> changeEquipmentDataMap = new ConcurrentHashMap<>(userData.getEquipmentMap());
                XiuXianEquipmentConfig equipmentCfg = config.getEquipmentConfigMap().get(userData.getTripodEquipment().getEquipmentId());
                if (equipmentCfg != null) {
                    changeEquipmentDataMap.put(equipmentCfg.getType(), userData.getTripodEquipment());
                    Map<Integer, Long> totalAttrMap = calcTotalAttr(changeEquipmentDataMap);
                    // 仙力值
                    long changePowerVal = powerFormula(totalAttrMap);
                    userData.getTripodEquipment().setDiffPowerVal(changePowerVal - userData.getPowerVal());
                }
            }
            player.notifyListener(eGamePlayerEventType.XiuXianXianLiRank.getValue(), rankArgs);
        } else if (isBreakUpgrade && !isSuccess){
            // 突破失败 增加渡劫CD
            userData.setLastBreakFailTime(curTimeSec);
            userData.setBreakCount(userData.getBreakCount() + 1);
            subPractice = needPracticeVal * config.getXIUXIAN_STATE_UPGRADE_FAIL_CONSUME()/1000;
        }
        // 扣除修为值
        userData.setPracticeVal(userData.getPracticeVal() - subPractice);
        userData.setUpdateOption();

        // 同步跨服广播
        if (isBreakUpgrade) {
            if (isSuccess) {
                syncMountRoomOpToCross(activityId, eXiuXianType.RoomOpType.StateBreak.getValue(), 1);
            }else {
                syncMountRoomOpToCross(activityId, eXiuXianType.RoomOpType.StateBreak.getValue(), 0);
            }
        }

        // 返回客户端
        XiuXianProto.XiuXianStateUpgradeRespMsg.Builder builder = XiuXianProto.XiuXianStateUpgradeRespMsg.newBuilder();
        builder.setRet(0);
        builder.setResult(isSuccess);
        builder.setStateId(userData.getStateId());
        builder.setSubPracticeVal(subPractice);
        builder.setPracticeVal(userData.getPracticeVal());
        builder.setPracticeSpeed(userData.getPracticeSpeed());
        builder.setBreakFailTime(userData.getLastBreakFailTime());
        builder.addAllItem(XiuXianPb.parseXiuXianItemMsgList(userData.getItems()));
        builder.setTripodEquipment(XiuXianPb.parseEquipmentInfoTemp(userData.getTripodEquipment()));
        for (Map.Entry<Integer, Long> entry : userData.getProperty().getAttrMap().entrySet()) {
            builder.addAttrList(XiuXianPb.parseXiuXianAttrInfoTemp(entry.getKey(), entry.getValue()));
        }
        player.sendPacket(ClientProtocol.U_XIU_XIAN_STATE_UPGRADE, builder);
        // 突破日志
        if (isBreakUpgrade) {
            AutoLogMgr.add(new LogXiuXianStateUpgrade(userData.getUserId(), userData.getActivityId(), oldStateId, userData.getStateId(), userData.getPowerVal(), isSuccess));
        }
        // 修为日志
        AutoLogMgr.add(new LogXiuXianPracticeVal(userData.getUserId(), userData.getActivityId(), userData.getStateId(), 3, -subPractice, userData.getPracticeVal(), 0));
        // 仙力日志
        AutoLogMgr.add(new LogXiuXianPowerVal(userData.getUserId(), userData.getActivityId(), 1, userData.getPowerVal()-oldPowerVal,
                userData.getPowerVal(), oldStateId, userData.getStateId(), 0, new ArrayList<>(userData.getEquipmentMap().values())));
        return 0;
    }
    /**
     * 是否渡劫成功
     * 判断条件1、小于最小仙力直接失败 2、计算一个概率值，随机是否能成功
     */
    public boolean isCanBreakSuccess(XiuXianStateConfig stateConfig) {
        boolean isSuccess = false;
        // 仙力标准
        String[] needXianLiArray = stateConfig.getNeedXianLi().split("=");
        long needXianLi = Long.valueOf(needXianLiArray[1]);
        // 配置最低仙力
        String[] minXianLiArray = stateConfig.getMinXianLi().split("=");
        long minXianLi = Long.valueOf(minXianLiArray[1]);
        // 小于最小仙力
        if (userData.getPowerVal() < minXianLi) {
            return isSuccess;
        }
        //XiuXianConfig config = XiuXianMgr.getConfig();
        //String[] paramArray = config.getXIUXIAN_STATE_UPGRADE_FAIL_PRM().split("\\|");
        //double xianLiRatio = Math.pow((double)userData.getPowerVal()/needXianLi*Double.parseDouble(paramArray[1]), 2d);
        // 渡劫公式  MIN（参数1/1000*（玩家仙力/标准仙力*参数2）^2 + 参数3，参数4）/100
        //double ratio = Math.min(Double.parseDouble(paramArray[0])/1000 * xianLiRatio + Double.parseDouble(paramArray[2]), Double.parseDouble(paramArray[3]))/100;
        double ratio = BigDecimal.valueOf(userData.getPowerVal() - minXianLi).divide(BigDecimal.valueOf(needXianLi - minXianLi), 3, BigDecimal.ROUND_DOWN).doubleValue();
        double randomDouble = randomHelper.nextDouble(0, 1);
        if (ratio >= randomDouble) {
            isSuccess = true;
        }
        return isSuccess;
    }
    /**
     * 减少渡劫CD 策划改需求，不需要的接口
     */
    public int breakCdReduce(int activityId, int useCount) {
        return GameErrorCode.E_XIU_XIAN_PARAM_ERROR;
    }

    /**
     * 随机装备出来
     */
    public int equipmentRandom(int equipmentType, int quality) {
        List<Integer> equipmentList = new ArrayList<>();
        XiuXianConfig config = XiuXianMgr.getConfig();
        for (XiuXianEquipmentConfig equipmentCfg : config.getEquipmentConfigMap().values()) {
            if (equipmentCfg.getType() == equipmentType && equipmentCfg.getQuality() == quality) {
                equipmentList.add(equipmentCfg.getId());
            }
        }
        if (equipmentList.isEmpty()) {
            return 0;
        }
        int equipmentId = equipmentList.get(randomHelper.next(equipmentList.size()));
        return equipmentId;
    }
    /**
     * 计算战斗属性
     */
    public void calcBattleProperty() {
        Map<Integer, Long> totalAttrMap = calcTotalAttr(userData.getEquipmentMap());
        // 仙力值
        long newPowerVal = powerFormula(totalAttrMap);
        XiuXianPveUserProperty property = userData.getProperty();
        property.setAttrMap(totalAttrMap);
        userData.setUpdateOption();
        // 计算仙力
        updatePowerVal(newPowerVal);
    }
    /**
     * 计算装备的总属性
     */
    public Map<Integer, Long> calcTotalAttr(Map<Integer, XiuXianEquipmentData> equipmentDataMap) {
        XiuXianConfig config = XiuXianMgr.getConfig();
        /**
         * 公式： 基础属性 =（装备的基础属性 + 等级的基础属性）*（1+境界千分比）
         *  基础属性 = 装备基础血量、攻击*（1+境界加成）*升级参数
         * */
        // 装备基础属性, 装备id、属性id、属性值
        Map<Integer, Map<Integer, Long>> equipmentBaseAttrMap = new ConcurrentHashMap<>();
        // 装备进阶属性, 装备id、属性id、属性值
        Map<Integer, Map<Integer, Long>> equipmentAdvanceAttrMap = new ConcurrentHashMap<>();

        // 基础属性
        for (XiuXianEquipmentData equipmentData : equipmentDataMap.values()) {
            /**基础属性获取*/
            // 装备的基础属性
            Map<Integer, Long> baseAttrMap = new ConcurrentHashMap<>();               // 基础属性
            XiuXianEquipmentConfig equipmentCfg = config.getEquipmentConfigMap().get(equipmentData.getEquipmentId());
            mergeStrToMap(baseAttrMap, equipmentCfg.getAttribute());
            // 基础属性的升级参数
            Map<Integer, Long> baseUpgradeParamMap = new ConcurrentHashMap<>();       // 基础属性的升级参数
            int upgradeBaseType = eXiuXianType.EquipmentUpgradeType.baseAttr.getValue();
            XiuXianUpgradeConfig upgradeConfig = config.getUpgradeConfigMap().getOrDefault(upgradeBaseType, new ConcurrentHashMap<>()).get(equipmentData.getBaseLv());
            if (upgradeConfig != null) {
                mergeStrToMap(baseUpgradeParamMap, upgradeConfig.getUpgradeAtt());
            }
            Map<Integer, Long> tempBaseAttrMap = new ConcurrentHashMap<>();
            for (Map.Entry<Integer, Long> entry : baseAttrMap.entrySet()) {
                long attrVal = (long)(baseUpgradeParamMap.getOrDefault(entry.getKey(), 0L) * entry.getValue() / 1000d);
                tempBaseAttrMap.put(entry.getKey(), attrVal);
            }
            equipmentBaseAttrMap.put(equipmentData.getEquipmentId(), tempBaseAttrMap);
            /**进阶属性**/
            equipmentAdvanceAttrMap.put(equipmentData.getEquipmentId(), equipmentData.getAttrAdvanceMap());
        }
        // 基础属性
        Map<Integer, Long> baseAttrMap = new ConcurrentHashMap<>();               // 基础属性
        XiuXianStateConfig stateConfig = config.getStateConfigMap().get(userData.getStateId());
        if (stateConfig != null) {
              //不算每个装备的基础属性 境界加成
            for (Map<Integer, Long> attrMap : equipmentBaseAttrMap.values()) {
                for (Map.Entry<Integer, Long> entry : attrMap.entrySet()) {
                    // 千分比向下取整
                    long addValue = entry.getValue();
                    attrMap.put(entry.getKey(), addValue);
                    baseAttrMap.put(entry.getKey(), baseAttrMap.getOrDefault(entry.getKey(), 0L) + addValue);
                }
            }
        }

        // 仙力计算
        // 合并基本属性、高级属性
        Map<Integer, Long> totalAttrMap = new ConcurrentHashMap<>();
        for (Map<Integer, Long> attrMap : equipmentAdvanceAttrMap.values()) {
            for (Map.Entry<Integer, Long> entry : attrMap.entrySet()) {
                totalAttrMap.put(entry.getKey(), totalAttrMap.getOrDefault(entry.getKey(), 0L) + entry.getValue());
            }
        }
        for (Map.Entry<Integer, Long> entry : baseAttrMap.entrySet()) {
            totalAttrMap.put(entry.getKey(), totalAttrMap.getOrDefault(entry.getKey(), 0L)+entry.getValue());
        }
        // 攻速加上基础属性
        totalAttrMap.put(eXiuXianType.BattleAttrType.AtkSpeed.getValue(),
                totalAttrMap.getOrDefault(eXiuXianType.BattleAttrType.AtkSpeed.getValue(), 0L) + config.getXIUXIAN_BASE_ATTACK_SPEED());

        // 境界基础属性加成 变更 改成基础攻击加固定值，血量是攻击力 * 10
        if (stateConfig != null) {
            int addition = stateConfig.getAttributeAdd();
            //攻击力
            long old = totalAttrMap.getOrDefault(eXiuXianType.BattleAttrType.Atk.getValue(), 0L);
            totalAttrMap.put(eXiuXianType.BattleAttrType.Atk.getValue(), old + addition);

            //血量
            old = totalAttrMap.getOrDefault(eXiuXianType.BattleAttrType.Hp.getValue(), 0L);
            totalAttrMap.put(eXiuXianType.BattleAttrType.Hp.getValue(), old + addition * config.getXIUXIAN_HP_CAP_PARM() / 1000);
        }

        // 属性最大值限制
        Map<Integer, Long> tempMaxMap = new ConcurrentHashMap<>();
        mergeStrToMap(tempMaxMap, config.getXIUXIAN_ATTRIBUTE_VALUE_MAX());
        for (Map.Entry<Integer, Long> entry : totalAttrMap.entrySet()) {
            long value = entry.getValue();
            int attrId = entry.getKey();
            if (tempMaxMap.containsKey(attrId)) {
                long newValue = Math.min(tempMaxMap.get(attrId), value);
                totalAttrMap.put(attrId, newValue);
            }
        }
        return totalAttrMap;
    }
    /**
     * 仙力计算公式
     */
    public long powerFormula(Map<Integer, Long> totalAttrMap) {
        XiuXianConfig config = XiuXianMgr.getConfig();
        List<Long> xianliPrm = StringUtils.stringToLongList(config.getXIUXIAN_XIANLI_PRM(), "\\|");
        // 血量
        long hp = totalAttrMap.getOrDefault(eXiuXianType.BattleAttrType.Hp.getValue(), 0L);
        // 攻击力
        long atk = totalAttrMap.getOrDefault(eXiuXianType.BattleAttrType.Atk.getValue(), 0L);
        // 暴击
        long critRatio = totalAttrMap.getOrDefault(eXiuXianType.BattleAttrType.CritRatio.getValue(), 0L);
        // 坚韧
        long tenacityRatio = totalAttrMap.getOrDefault(eXiuXianType.BattleAttrType.TenacityRatio.getValue(), 0L);
        // 攻速
        long atkSpeed = totalAttrMap.getOrDefault(eXiuXianType.BattleAttrType.AtkSpeed.getValue(), 0L);
        // 闪避
        long dodgeRatio = totalAttrMap.getOrDefault(eXiuXianType.BattleAttrType.DodgeRatio.getValue(), 0L);
        // 命中
        long hitRatio = totalAttrMap.getOrDefault(eXiuXianType.BattleAttrType.HitRatio.getValue(), 0L);
        // 吸血
        long suckRatio = totalAttrMap.getOrDefault(eXiuXianType.BattleAttrType.SuckRatio.getValue(), 0L);
        // 开始计算
        //double param1 = (double)hp * atk * (1 + atkSpeed/1000d);
        //BigDecimal param1 = BigDecimal.valueOf(hp * atk).multiply(BigDecimal.valueOf(1 + (double)atkSpeed / 1000));

        BigDecimal param1 = BigDecimal.valueOf(Math.pow(hp * atk, (double)xianliPrm.get(0) / 1000)).multiply(BigDecimal.valueOf((double)atkSpeed / 1000));

        //double param2 = ((double)xianliPrm.get(0) + suckRatio)/xianliPrm.get(1);
        //BigDecimal param2 = BigDecimal.valueOf(xianliPrm.get(0) + suckRatio).divide(BigDecimal.valueOf(xianliPrm.get(1)), 10, BigDecimal.ROUND_DOWN);
        BigDecimal param2 = BigDecimal.valueOf(xianliPrm.get(1) + suckRatio);

        //double param3 = 1;
        //if (xianliPrm.get(3) > dodgeRatio * hitRatio) {
            //param3 = (double)xianliPrm.get(2)/(xianliPrm.get(3) - (dodgeRatio + hitRatio));
        BigDecimal param3 = BigDecimal.valueOf(xianliPrm.get(2)).divide(BigDecimal.valueOf(xianliPrm.get(3) - (dodgeRatio + hitRatio)), 10, BigDecimal.ROUND_DOWN);
        //}

        //double param4 = ((double)xianliPrm.get(4) + critRatio + tenacityRatio)/xianliPrm.get(5);
        BigDecimal param4 = BigDecimal.valueOf(xianliPrm.get(4) + critRatio + tenacityRatio).divide(BigDecimal.valueOf(xianliPrm.get(5)), 10, BigDecimal.ROUND_DOWN);

        //double param5 = 1d/xianliPrm.get(6);
        BigDecimal param5 = BigDecimal.valueOf(1).divide(BigDecimal.valueOf(xianliPrm.get(6)), 10, BigDecimal.ROUND_DOWN);

        //long powerValue = (long) (param1 * param2 * param3 * param4 * param5);
        BigDecimal result = param5.multiply(param1).multiply(param2).multiply(param3).multiply(param4);

        return result.longValue();
    }
    /**
     * 凡人虚空鼎抽取法宝
     */
    public int tripodDraw(int activityId) {
        // 检测活动参数
        int checkRet = checkActivityData(activityId);
        if(checkRet != 0) {
            return checkRet;
        }
        XiuXianConfig config = XiuXianMgr.getConfig();

        XiuXianTripodConfig tripodCfg = config.getTripodConfigMap().get(userData.getTripodLv());
        if (null == tripodCfg) {
            return GameErrorCode.E_XIU_XIAN_PARAM_ERROR;
        }
        if (userData.getTripodEquipment().getEquipmentId() != 0) {
            return GameErrorCode.E_XIU_XIAN_TRIPOD_HAS_EQUIPMENT;
        }
        // 检测机缘点是否足够
        if (userData.getLuckPoint() < tripodCfg.getExtractConsume()) {
            return GameErrorCode.E_XIU_XIAN_TRIPOD_DRAW_LIMIT;
        }

        // 检测经验是否足够
        String[] needItemArray = tripodCfg.getNeedItem().split("=");
        if (needItemArray.length != 2) {
            return GameErrorCode.E_XIU_XIAN_CFG_ERROR;
        }
        int needTripodExp = Integer.parseInt(needItemArray[1]);
        if (userData.getTripodExp() >= needTripodExp) {
            // 虚空鼎经验满了
            return GameErrorCode.E_XIU_XIAN_PARAM_ERROR;
        }


        // 抽取前机缘点
        int beforeLuckPoint = userData.getLuckPoint();

        long newDrawTimes = userData.getDrawTimes() + 1;       // 抽取次数（包含本次）

        int equipmentId = 0;
        int baseLv = 0;
        if (userData.getEquipmentMap().size() == 0) {
            // 初始装备
            List<Integer> initEquipmentList = StringUtils.stringToIntegerList(config.getXIUXIAN_INIT_EQUIPMENT(), "\\|");
            if (initEquipmentList.size() < 2) {
                return GameErrorCode.E_XIU_XIAN_CFG_ERROR;
            }
            equipmentId = initEquipmentList.get(0);
            baseLv = initEquipmentList.get(1);
        } else {
            // 随机品质
            int quality = RandomHelper.getRandomKeyByWeight(tripodCfg.getQualityWeight());
            //抽取达到10次或者50次，必得仙器级别的法宝
            Map<Long,Integer> qualityRegularMap = config.getQualityRegularMap();
            if (qualityRegularMap.containsKey(newDrawTimes)) {
                quality = qualityRegularMap.get(newDrawTimes);
            }
            // 随机法宝类型
            int equipmentType = RandomHelper.getRandomKeyByWeight(tripodCfg.getTypeRandom());
            // 随机法宝基础等级
            baseLv = RandomHelper.getRandomKeyByWeight(tripodCfg.getLevelRandom());
            // 随机装备
            equipmentId = equipmentRandom(equipmentType, quality);
            //抽取达到31次必得本命法宝，青云峰云剑（等级随机）
            Map<Long,Integer> fabaoIdRegularMap = config.getFabaoIdRegularMap();
            if (fabaoIdRegularMap.containsKey(newDrawTimes)) {
                equipmentId = fabaoIdRegularMap.get(newDrawTimes);
            }
        }

        XiuXianEquipmentConfig equipmentCfg = config.getEquipmentConfigMap().get(equipmentId);
        if (null == equipmentCfg || baseLv == 0) {
            return GameErrorCode.E_XIU_XIAN_CFG_ERROR;
        }

        // 随机进阶属性
        Map<Integer, Long> attrAdvanceMap = randomAdvanceAttr(equipmentCfg.getAdvancedAttribute());

        // 计算替换后的仙力
        XiuXianEquipmentData equipmentData = new XiuXianEquipmentData(equipmentCfg.getId(), baseLv, attrAdvanceMap);
        Map<Integer, XiuXianEquipmentData> changeEquipmentDataMap = new ConcurrentHashMap<>(userData.getEquipmentMap());
        changeEquipmentDataMap.put(equipmentCfg.getType(), equipmentData);
        Map<Integer, Long> totalAttrMap = calcTotalAttr(changeEquipmentDataMap);
        // 仙力值
        long changePowerVal = powerFormula(totalAttrMap);
        equipmentData.setDiffPowerVal(changePowerVal - userData.getPowerVal());


        // 更新内存数据
        userData.setTripodEquipment(equipmentData);
        userData.setLuckPoint(userData.getLuckPoint() - tripodCfg.getExtractConsume());
        userData.setDrawTimes(newDrawTimes);

        // 抽奖后机缘点
        int afterLuckPoint = userData.getLuckPoint();

        //  虚天元灵转换
        GoodsInfo goodsInfo = GoodsMgr.getGoodsById(config.getXIUXIAN_JIYUANDIAN_ITEM_ID());
        long score = 0;
        if (goodsInfo != null) {
            score = goodsInfo.getParamList().get(0).multiply(BigInteger.valueOf(tripodCfg.getExtractConsume())).longValue();
        }
        player.getModule(CurrencyModule.class).addCurrency(new Property(config.getXIUXIAN_XUTIANYUANLING_ITEM_ID(), score), eLogMoneyType.XiuXianActivity, eLogMoneyType.XiuXianTripodDraw);
        //  抽到稀有法宝 同步到跨服
        if (equipmentCfg.getQuality() >= config.getXIUXIAN_EQUIPMENT_RARE()) {
            syncMountRoomOpToCross(activityId, eXiuXianType.RoomOpType.RareEquipment.getValue(), equipmentId);
        }

        // 返回客户端
        XiuXianProto.XiuXianTripodDrawRespMsg.Builder builder = XiuXianProto.XiuXianTripodDrawRespMsg.newBuilder();
        builder.setRet(0);
        builder.setEquipment(XiuXianPb.parseEquipmentInfoTemp(equipmentData));
        builder.setLuckPoint(userData.getLuckPoint());
        builder.setScore(score);
        builder.setDrawTimes(userData.getDrawTimes());
        player.sendPacket(ClientProtocol.U_XIU_XIAN_TRIPOD_DRAW, builder);
        // 日志
        AutoLogMgr.add(new LogXiuXianTripodOp(userData.getUserId(), userData.getActivityId(), userData.getTripodLv(), beforeLuckPoint,
                tripodCfg.getExtractConsume(), afterLuckPoint, equipmentData.getEquipmentId(), equipmentData.getBaseLv(), false, 0));
        // 机缘点日志
        AutoLogMgr.add(new LogXiuXianLuckPoint(userData.getUserId(), userData.getActivityId(), 2, -tripodCfg.getExtractConsume(), userData.getLuckPoint()));
        return 0;
    }

    /**
     * 凡人虚空鼎升级
     *  升级已当前等级为升级条件，如1级升2级，读1级的条件进行升级
     */
    public int tripodUpgrade(int activityId) {
        // 检测活动参数
        int checkRet = checkActivityData(activityId);
        if(checkRet != 0) {
            return checkRet;
        }
        XiuXianConfig config = XiuXianMgr.getConfig();

        int oldLv = userData.getTripodLv();
        int newLv = oldLv + 1;
        XiuXianTripodConfig newTripodInfoConfig = config.getTripodConfigMap().get(newLv);
        XiuXianTripodConfig oldTripodInfoConfig = config.getTripodConfigMap().get(oldLv);
        if (newTripodInfoConfig == null || oldTripodInfoConfig == null) {
            // 找不到配置，提示达到最高级
            return GameErrorCode.E_XIU_XIAN_UPGRADE_LIMIT;
        }

        // 检测经验是否足够
        String[] needItemArray = oldTripodInfoConfig.getNeedItem().split("=");
        if (needItemArray.length != 2) {
            return GameErrorCode.E_XIU_XIAN_CFG_ERROR;
        }
        int needTripodExp = Integer.parseInt(needItemArray[1]);
        if (needTripodExp > userData.getTripodExp()) {
            // 虚空鼎经验不足
            return GameErrorCode.E_XIU_XIAN_TRIPOD_EXP_LIMIT;
        }

        // 检测境界限制
        if(oldTripodInfoConfig.getStateLimit() != 0 && userData.getStateId() < oldTripodInfoConfig.getStateLimit()){
            return GameErrorCode.E_XIU_XIAN_UPGRADE_LIMIT;
        }

        // 更新内存数据
        userData.setTripodExp(userData.getTripodExp()-needTripodExp);
        userData.setTripodLv(newLv);

        // 返回客户端
        XiuXianProto.XiuXianTripodUpgradeRespMsg.Builder builder = XiuXianProto.XiuXianTripodUpgradeRespMsg.newBuilder();
        builder.setRet(0);
        builder.setTripodExp(userData.getTripodExp());
        builder.setTripodLv(userData.getTripodLv());
        player.sendPacket(ClientProtocol.U_XIU_XIAN_TRIPOD_UPGRADE, builder);
        // 日志
        AutoLogMgr.add(new LogXiuXianTripodUpgrade(userData.getUserId(), userData.getActivityId(), oldLv, newLv));
        return 0;
    }

    /**
     * 法宝替换
     */
    public int equipmentReplace(int activityId, int equipmentId) {
        // 检测活动参数
        int checkRet = checkActivityData(activityId);
        if(checkRet != 0) {
            return checkRet;
        }
        XiuXianConfig config = XiuXianMgr.getConfig();

        // TODO 虚空鼎装备、客户端传的装备，进行检测
        if (userData.getTripodEquipment().getEquipmentId() == 0 || userData.getTripodEquipment().getEquipmentId() != equipmentId) {
            return GameErrorCode.E_XIU_XIAN_PARAM_ERROR;
        }
        XiuXianEquipmentConfig equipmentCfg = config.getEquipmentConfigMap().get(equipmentId);
        if (null == equipmentCfg) {
            return GameErrorCode.E_XIU_XIAN_CFG_ERROR;
        }

        // 更新内存数据
        Map<Integer, XiuXianEquipmentData> equipmentMap = userData.getEquipmentMap();
        XiuXianEquipmentData oldEquipmentObj = equipmentMap.getOrDefault(equipmentCfg.getType(), new XiuXianEquipmentData());
        equipmentMap.put(equipmentCfg.getType(), userData.getTripodEquipment());

        // 旧的仙力值
        long oldPowerVal = userData.getPowerVal();

        // 更新战斗属性
        calcBattleProperty();

        // 替换虚天鼎内装备 更新替换后仙力值
        oldEquipmentObj.setDiffPowerVal(oldPowerVal - userData.getPowerVal());
        userData.setTripodEquipment(oldEquipmentObj);

        // 返回客户端
        XiuXianProto.XiuXianEquipmentReplaceRespMsg.Builder builder = XiuXianProto.XiuXianEquipmentReplaceRespMsg.newBuilder();
        builder.setRet(0);
        builder.setTripodEquipment(XiuXianPb.parseEquipmentInfoTemp(userData.getTripodEquipment()));
        builder.setProperty(XiuXianPb.parseXiuXianPveUserPropertyTemp(userData.getProperty()));
        builder.setPowerVal(userData.getPowerVal());
        for (XiuXianEquipmentData data : userData.getEquipmentMap().values()) {
            XiuXianProto.EquipmentInfoTemp.Builder parseEquipmentInfo = XiuXianPb.parseEquipmentInfoTemp(data);
            if(parseEquipmentInfo != null) {
                builder.addEquipmentList(parseEquipmentInfo);
            }
        }
        player.sendPacket(ClientProtocol.U_XIU_XIAN_EQUIPMENT_REPLACE, builder);
        // 仙力日志
        AutoLogMgr.add(new LogXiuXianPowerVal(userData.getUserId(), userData.getActivityId(), 2, userData.getPowerVal()-oldPowerVal,
                userData.getPowerVal(), 0, userData.getStateId(), equipmentId, new ArrayList<>(userData.getEquipmentMap().values())));
        return 0;
    }

    /**
     * 装备回收(虚空鼎内的装备回收)
     * @param equipmentId: 客户端上传检验
     */
    public int equipmentRecycle(int activityId, int equipmentId) {
        // 检测活动参数
        int checkRet = checkActivityData(activityId);
        if(checkRet != 0) {
            return checkRet;
        }
        XiuXianConfig config = XiuXianMgr.getConfig();
        XiuXianEquipmentConfig equipmentConfig = config.getEquipmentConfigMap().get(equipmentId);
        if (null == equipmentConfig || userData.getTripodEquipment().getEquipmentId() != equipmentId) {
            return GameErrorCode.E_XIU_XIAN_PARAM_ERROR;
        }
        // 回收奖励
        XiuXianUpgradeConfig upgradeConfig = config.getUpgradeConfigMap().getOrDefault(eXiuXianType.EquipmentUpgradeType.EquipmentTripodExp.getValue(), new ConcurrentHashMap<>()).get(userData.getTripodEquipment().getBaseLv());
        if (upgradeConfig == null) {
            return GameErrorCode.E_XIU_XIAN_PARAM_ERROR;
        }
        Map<Integer, Long> tempAttrMap = new ConcurrentHashMap<>();
        mergeStrToMap(tempAttrMap, upgradeConfig.getUpgradeAtt());
        int addTripodExp = tempAttrMap.getOrDefault(equipmentConfig.getQuality(), 0L).intValue();
        if (addTripodExp <= 0) {
            return GameErrorCode.E_XIU_XIAN_PARAM_ERROR;
        }
        // 回收的装备
        XiuXianEquipmentData recycleTripodEquipment = userData.getTripodEquipment();

        int beforeLuckPoint = userData.getLuckPoint();

        // 更新内存 虚空鼎置空、更新获得的虚空鼎经验
        userData.setTripodEquipment(new XiuXianEquipmentData());
        userData.setTripodExp(userData.getTripodExp() + addTripodExp);

        int afterLuckPoint = userData.getLuckPoint();

        // 返回客户端
        XiuXianProto.XiuXianEquipmentRecycleRespMsg.Builder builder = XiuXianProto.XiuXianEquipmentRecycleRespMsg.newBuilder();
        builder.setRet(0);
        builder.setTripodExp(userData.getTripodExp());
        player.sendPacket(Protocol.U_XIU_XIAN_EQUIPMENT_RECYCLE, builder);
        // 日志
        AutoLogMgr.add(new LogXiuXianTripodOp(userData.getUserId(), userData.getActivityId(), userData.getTripodLv(), beforeLuckPoint,
                0, afterLuckPoint, recycleTripodEquipment.getEquipmentId(), recycleTripodEquipment.getBaseLv(), true, addTripodExp));
        return 0;
    }

    /**
     * 检测是否可以进入地图
     */
    public boolean isCanEnterMission(XiuXianMissionConfig enterMissionCfg) {
        XiuXianConfig config = XiuXianMgr.getConfig();
        for (XiuXianMissionConfig missionConfig : config.getMissionConfigMap().values()) {
            if (enterMissionCfg.getFloor() <= missionConfig.getFloor()) {
                continue;
            }
            // 低难度还未完成
            XiuXianMissionData missionData = missionMap.get(missionConfig.getId());
            if (missionData == null || !missionData.getIsFinish()) {
                return false;
            }
        }
        // 判断下前置关卡是否存在，存在再判断是否完成
        int curId = enterMissionCfg.getId();
        if (config.getMissionConfigMap().containsKey(curId - 1)) {
            XiuXianMissionData missionData = missionMap.get(curId - 1);
            if (missionData == null || !missionData.getIsFinish()) {
                return false;
            }
        }
        return true;
    }

    /**
     * 历练进入地图
     * 判断条件
     * 1、首层不用判断
     * 2、非首层判断是否格子全部完成
     */
    public int missionEnterFloor(int activityId, int missionId) {
        // 检测活动参数
        int checkRet = checkActivityData(activityId);
        if(checkRet != 0) {
            return checkRet;
        }
        XiuXianConfig config = XiuXianMgr.getConfig();

        // 获取进入地图的配置
        XiuXianMissionConfig enterMissionCfg = config.getMissionConfigMap().get(missionId);
        if (null == enterMissionCfg) {
            return GameErrorCode.E_XIU_XIAN_PARAM_ERROR;
        }

        XiuXianMissionData missionData = missionMap.get(enterMissionCfg.getId());
        if (missionData != null) {
            return GameErrorCode.E_XIU_XIAN_PARAM_ERROR;
        }

        // 难度检测是否可以进入地图
        if (!isCanEnterMission(enterMissionCfg)) {
            return GameErrorCode.E_XIU_XIAN_STATE_LIMIT;
        }

        // 境界限制
        if (enterMissionCfg.getStateLimit() > 0 && enterMissionCfg.getStateLimit() > userData.getStateId()) {
            return GameErrorCode.E_XIU_XIAN_STATE_LIMIT;
        }

        // 更新内存数据
        missionData = new XiuXianMissionData();
        missionData.setActivityId(config.getActivityInfo().getActivityId());
        missionData.setUserId(userData.getUserId());
        missionData.setMissionType(enterMissionCfg.getType());
        missionData.setMissionId(enterMissionCfg.getId());
        missionData.setHasExploreGridList(new ArrayList<>());
        missionData.setMissionId(enterMissionCfg.getId());
        missionData.setInsertOption();
        missionMap.put(enterMissionCfg.getId(), missionData);

        // 返回客户端
        XiuXianProto.XiuXianMissionEnterFloorRespMsg.Builder resp = XiuXianProto.XiuXianMissionEnterFloorRespMsg.newBuilder();
        resp.setRet(0);
        player.sendPacket(ClientProtocol.U_XIU_XIAN_MISSION_ENTER_FLOOR, resp);
        return 0;
    }
    /**
     * 检测是否可以探索
     * 出身点（0，0）左下角，检测上、右两个点
     * 非出生点，检测上下左右四个点
     */
    private int checkCanExplore(List<XiuXianGridPositionData> positionList, int x, int y, XiuXianMissionConfig paramMissionCfg) {
        int result = GameErrorCode.E_XIU_XIAN_GRID_EXPLORE_LIMIT;
        // 出生点检测
        if (positionList.size() == 0) {
            // 获取起始点位置
            int startX = -1;
            int startY = -1;
            String[] terrainArray = paramMissionCfg.getTerrain().split("\\|");
            for(String pos : terrainArray) {
                List<String> pointList = Arrays.asList(pos.split("="));
                if (pointList.size() != 2) {
                    continue;
                }
                int eventId = Integer.parseInt(pointList.get(1));
                if (eventId == 1000) {
                    String[] posArray = pointList.get(0).split(",");
                    startX = Integer.parseInt(posArray[0]);
                    startY = Integer.parseInt(posArray[1]);
                    break;
                }
            }
            if (startX == -1 ) {
                return GameErrorCode.E_XIU_XIAN_PARAM_ERROR;
            }
            if ((startX == x-1 && startY == y) || (startX == x+1 && startY == y) ||
                    (startX == x && startY == y-1) || (startX == x && startY == y+1)) {
                return 0;
            }
            return GameErrorCode.E_XIU_XIAN_GRID_EXPLORE_LIMIT;
        }
        // 是否已经探索完成
        for (XiuXianGridPositionData posData : positionList) {
            if (posData.getX() == x && posData.getY() ==y && posData.getFinishStatus() == eXiuXianType.GridStatus.Finish.getValue()) {
                // 已经套索
                return GameErrorCode.E_XIU_XIAN_GRID_HAS_EXPLORE;
            }
            if ((posData.getX() == x-1 && posData.getY() == y) || (posData.getX() == x+1 && posData.getY() == y) ||
                    (posData.getX() == x && posData.getY() == y-1) || (posData.getX() == x && posData.getY() == y+1)) {
                // 可以探索
                result = 0;
            }
        }
        return result;
    }
    /**
     * 获取地图坐标的格子事件
     */
    private int getPositionEvent(XiuXianMissionConfig missionCfg, int x, int y) {
        String[] terrainArray = missionCfg.getTerrain().split("\\|");
        for(String pos : terrainArray) {
            List<String> pointList = Arrays.asList(pos.split("="));
            if (pointList.size() != 2) {
                return GameErrorCode.E_XIU_XIAN_CFG_ERROR;
            }
            String coordinateStr = pointList.get(0);
            String[] coordinateList = coordinateStr.split(",");
            if (coordinateList.length != 2) {
                return GameErrorCode.E_XIU_XIAN_CFG_ERROR;
            }
            if (Integer.parseInt(coordinateList[0]) == x && Integer.parseInt(coordinateList[1]) == y) {
                return Integer.parseInt(pointList.get(1));
            }
        }
        return 0;
    }
    /**
     * 合并string为map
     * string格式：param1=param2|param1=param2
     */
    private void mergeStrToMap(Map<Integer, Long> strMap, String str) {
        String[] strArray = str.split("\\|");
        for(String attrStr : strArray) {
            String[] attrArray = attrStr.split("=");
            if (attrArray.length < 2) {
                continue;
            }
            int key = Integer.parseInt(attrArray[0]);
            long value = Long.parseLong(attrArray[1]);
            strMap.put(key, strMap.getOrDefault(key, 0L) + value);
        }
    }
    /**
     * npc事件逻辑
     */
    private XiuXianBattleScene npcEventLogic(XiuXianEventConfig eventCfg, int missionId, int x, int y) {
        XiuXianBattleScene battleScene = buildBattleScene(eventCfg, missionId, x, y);
        if (battleScene == null) {
            return battleScene;
        }
        battleScene.buildBattleResult(0);
        tempBattleScene = battleScene;
        return battleScene;
    }
    /**
     * 生成战场
     */
    private XiuXianBattleScene buildBattleScene(XiuXianEventConfig eventCfg, int missionId, int x, int y) {
        // 拦截没有战斗属性
        if (userData.getProperty().getAttrMap().getOrDefault(eXiuXianType.BattleAttrType.Hp.getValue(), 0L) == 0L
                || userData.getProperty().getAttrMap().getOrDefault(eXiuXianType.BattleAttrType.Atk.getValue(), 0L) == 0L) {
            return null;
        }
        XiuXianConfig config = XiuXianMgr.getConfig();
        int uniqueId = 1;       // 唯一id
        // 创建战斗场景
        XiuXianBattleScene battleScene = new XiuXianBattleScene(missionId, x, y, eventCfg);
        // TODO 1 代表有本命法宝
        int skillId = 1;
        long skillAtk = 0;
        if (!isHasExclusive()) {
            skillId = 0;
        } else {
            skillAtk = userData.getProperty().getAttrMap().getOrDefault(eXiuXianType.BattleAttrType.Atk.getValue(), 0L) * config.getXIUXIAN_PLAYER_SKILL_DAMAGE_PRM() / 1000;
        }

        XiuXianBattleData attackerData = new XiuXianBattleData(1, uniqueId++, 0, userData.getProperty().getAttrMap(), skillId, skillAtk);
        List<XiuXianBattleData> attackList = battleScene.getAttackList();
        attackList.add(attackerData);

        // 事件参数
        List<XiuXianBattleData> defenseList = battleScene.getDefenseList();
        String[] eventParamArray = eventCfg.getEventParameter().split("\\|");
        for(String paramStr : eventParamArray) {
            int npcId = Integer.parseInt(paramStr);
            XiuXianNpcConfig npcCfg = config.getNpcConfigMap().get(npcId);
            if (null == npcCfg) {
                return null;
            }
            Map<Integer, Long> attrMap = new ConcurrentHashMap<>();
            // 基础属性
            mergeStrToMap(attrMap, npcCfg.getAttribute());
            // 进阶属性
            mergeStrToMap(attrMap, npcCfg.getAdvancedAttribute());
            XiuXianBattleData defenseData = new XiuXianBattleData(2, uniqueId++, npcId, attrMap, 0, 0);
            defenseList.add(defenseData);
        }
        return battleScene;
    }
    /**
     *  统计玩家行为
     */
    public void npcEventBehaviorStat(int missionId, Map<Integer, BigInteger> goods) {
        if (tempBattleScene == null) {
            return;
        }
        XiuXianConfig config = XiuXianMgr.getConfig();
        Map<Integer, Integer> monsterCfgIdMap = new ConcurrentHashMap<>();
        List<Integer> itemCfgIdList = new ArrayList<>();

        for(XiuXianNpcConfig npcCfg : config.getNpcConfigMap().values()) {
            if (npcCfg.getType() == eXiuXianType.MissionNpcType.Monster.getValue()) {
                monsterCfgIdMap.put(npcCfg.getId(), npcCfg.getSmallType());
            }
            if (npcCfg.getType() == eXiuXianType.MissionNpcType.Item.getValue()) {
                itemCfgIdList.add(npcCfg.getId());
            }
        }
        // 统计击杀怪物
        int behaviorType = eXiuXianType.MissionBehaviorType.KillMonster.getValue();
        for (XiuXianBattleData battleData : tempBattleScene.getDefenseList()) {
            if (battleData.getHp() <=0 && monsterCfgIdMap.containsKey(battleData.getNpcId())) {
                int smallType = monsterCfgIdMap.get(battleData.getNpcId());
                String behaviorKey = getBehaviorKey(missionId, behaviorType, smallType);
                XiuXianUserBehaviorData data = behaviorMap.get(behaviorKey);
                if (data == null) {
                    // 记录小类
                    data = new XiuXianUserBehaviorData(config.getActivityInfo().getActivityId(), userData.getUserId(), missionId, behaviorType, smallType, 0);
                    behaviorMap.put(behaviorKey, data);
                    data.setInsertOption();
                }
                data.setCount(data.getCount() + 1);
            }
        }

        // 统计获得道具
        behaviorType = eXiuXianType.MissionBehaviorType.GetItem.getValue();
        for (Map.Entry<Integer, BigInteger> entry : goods.entrySet()) {
            int goodId = entry.getKey();
            int count = entry.getValue().intValue();
            if (itemCfgIdList.contains(goodId)) {
                String behaviorKey = getBehaviorKey(missionId, behaviorType, goodId);     // 获取行为key
                XiuXianUserBehaviorData data = behaviorMap.get(behaviorKey);
                if (data == null) {
                    data = new XiuXianUserBehaviorData(config.getActivityInfo().getActivityId(), userData.getUserId(), missionId, behaviorType, goodId, 0);
                    behaviorMap.put(behaviorKey, data);
                    data.setInsertOption();
                }
                data.setCount(data.getCount() + count);
            }
        }
    }

    /**
     * 探索格子
     */
    public int exploreGrid(int activityId, int missionId, int x, int y) {
        // 检测活动参数
        int checkRet = checkActivityData(activityId);
        if(checkRet != 0) {
            return checkRet;
        }
        XiuXianConfig config = XiuXianMgr.getConfig();

        XiuXianMissionConfig paramMissionCfg = config.getMissionConfigMap().get(missionId);
        if (null == paramMissionCfg) {
            return GameErrorCode.E_XIU_XIAN_PARAM_ERROR;
        }
        // 当前地图数据
        XiuXianMissionData missionData = missionMap.get(missionId);
        if (null == missionData) {
            return GameErrorCode.E_XIU_XIAN_PARAM_ERROR;
        }
        if (missionData.getIsFinish()) {
            return GameErrorCode.E_XIU_XIAN_MISSION_HAS_FINISH;
        }
        // 是否已经探索完成、是否可以探索
        int result = checkCanExplore(missionData.getHasExploreGridList(), x, y, paramMissionCfg);
        if (result != 0) {
            return result;
        }
        int eventId = getPositionEvent(paramMissionCfg, x, y);
        XiuXianEventConfig eventCfg = null;
        if (eventId == 2000) {
            // 记录最后一层
            missionData.setIsFinish(true);
            missionData.setHasExploreGridList(new ArrayList<>());
            userData.setUpdateOption();
        } else {
            eventCfg = config.getEventConfigMap().get(eventId);
            if (eventId == 0 || null == eventCfg) {
                return GameErrorCode.E_XIU_XIAN_CFG_ERROR;
            }
            tempBattleScene = null;
            if (eXiuXianType.EventType.isBattleEvent(eventCfg.getType())) {
                // 战斗事件生成结果 缓存战斗结果
                XiuXianBattleScene battleScene = npcEventLogic(eventCfg, missionId, x, y);
                if (battleScene == null) {
                    return GameErrorCode.E_XIU_XIAN_BATTLE_DATA_ERROR;
                }
            } else if (eXiuXianType.EventType.isTaskEvent(eventCfg.getType())) {
                // 是否已经探索接受任务 2023-01-22 14点热更
                for (XiuXianGridPositionData posData : missionData.getHasExploreGridList()) {
                    if (posData.getX() == x && posData.getY() ==y && posData.getFinishStatus() == eXiuXianType.GridStatus.NoFinish.getValue()) {
                        // 已经探索(未完成事件)
                        return GameErrorCode.E_XIU_XIAN_GRID_HAS_EXPLORE;
                    }
                }
                // 任务事件  记录为未完成状态
                XiuXianGridPositionData newGridObj = new XiuXianGridPositionData(x, y, eXiuXianType.GridStatus.NoFinish.getValue());
                List<XiuXianGridPositionData> hasExploreGridList = missionData.getHasExploreGridList();
                hasExploreGridList.add(newGridObj);
                missionData.setUpdateOption();
            }
        }
        // 返回客户端
        XiuXianProto.XiuXianExploreGridRespMsg.Builder resp = XiuXianProto.XiuXianExploreGridRespMsg.newBuilder();
        resp.setRet(0);
        if (eventCfg != null && eXiuXianType.EventType.isBattleEvent(eventCfg.getType())) {
            // npc对象列表
            for (XiuXianBattleData battleData : tempBattleScene.getDefenseList()) {
                resp.addNpcObjList(XiuXianPb.parseBattleObjectTemp(battleData));
            }
            // 战斗结果
            for (XiuXianBattleResult battleRes : tempBattleScene.getResultMap().values()) {
                resp.addBattleResultList(XiuXianPb.parseBattleEventResultInfoTemp(battleRes));
            }
        }
        resp.setMissionInfo(XiuXianPb.parseMissionInfoTemp(missionData));
        player.sendPacket(ClientProtocol.U_XIU_XIAN_EXPLORE_GRID, resp);
        return 0;
    }

    /**
     * 战斗事件选择对象
     * @param battleNum: 客户端上传没有播放的序号
     */
    public int npcSelect(int activityId, int id, int battleNum) {
        // 检测活动参数
        int checkRet = checkActivityData(activityId);
        if(checkRet != 0) {
            return checkRet;
        }
        // 当前不存在战斗
        if (null == tempBattleScene) {
            return GameErrorCode.E_XIU_XIAN_PARAM_ERROR;
        }
        if (battleNum < 1 || tempBattleScene.getResultMap().size() == 0 || battleNum > tempBattleScene.getBattleNum()) {
            return GameErrorCode.E_XIU_XIAN_PARAM_ERROR;
        }
        // 重置的战斗序号
        int resetBattleNum = battleNum - 1;
        if (battleNum == 1) {
            // 重新战斗
            XiuXianBattleScene battleScene = buildBattleScene(
                    tempBattleScene.getEventConfig(),
                    tempBattleScene.getMissionId(), tempBattleScene.getX(), tempBattleScene.getY());
            if (battleScene == null) {
                return GameErrorCode.E_XIU_XIAN_BATTLE_DATA_ERROR;
            }
            battleScene.buildBattleResult(id);
            tempBattleScene = battleScene;
        } else {
            // 重新生成结果
            int ret = tempBattleScene.selectNpc(id, resetBattleNum);
            if (ret != 0) {
                return ret;
            }
        }

        // 返回客户端
        XiuXianProto.XiuXianBattleSelectNpcRespMsg.Builder resp = XiuXianProto.XiuXianBattleSelectNpcRespMsg.newBuilder();
        resp.setRet(0);
        // 添加战斗结果
        for (XiuXianBattleResult battleRes : tempBattleScene.getResultMap().values()) {
            resp.addBattleResultList(XiuXianPb.parseBattleEventResultInfoTemp(battleRes));
        }
        player.sendPacket(ClientProtocol.U_XIU_XIAN_BATTLE_SELECT_NPC, resp);
        return 0;
    }
    /**
     * 释放技能
     * @param battleNum: 客户端上传没有播放的序号
     */
    public int skillOpen(int activityId, int battleNum) {
        // 检测活动参数
        int checkRet = checkActivityData(activityId);
        if(checkRet != 0) {
            return checkRet;
        }
        // 当前不存在战斗
        if (null == tempBattleScene) {
            return GameErrorCode.E_XIU_XIAN_PARAM_ERROR;
        }
        if (battleNum < 1 || tempBattleScene.getResultMap().size() == 0 || battleNum > tempBattleScene.getBattleNum()) {
            return GameErrorCode.E_XIU_XIAN_PARAM_ERROR;
        }
        // 检测是否有技能
        XiuXianBattleData attacker = tempBattleScene.getSkillAttacker();
        if (attacker.getSkillId() <= 0) {
            return GameErrorCode.E_XIU_XIAN_PARAM_ERROR;
        }
        XiuXianConfig config = XiuXianMgr.getConfig();
        // 重置的战斗序号
        int resetBattleNum = battleNum - 1;
        if (battleNum == 1) {
            // 重新战斗
            XiuXianBattleScene battleScene = buildBattleScene(
                    tempBattleScene.getEventConfig(),
                    tempBattleScene.getMissionId(), tempBattleScene.getX(), tempBattleScene.getY());
            if (battleScene == null) {
                return GameErrorCode.E_XIU_XIAN_BATTLE_DATA_ERROR;
            }
            // 重新生成结果
            int ret = battleScene.skillOpen(config, resetBattleNum);
            if (ret != 0) {
                return ret;
            }
            tempBattleScene = battleScene;
        } else {
            XiuXianBattleScene copyTempBattleScene = tempBattleScene.deepCopyUsingSerialization();
            // 重新生成结果
            int ret = tempBattleScene.skillOpen(config, resetBattleNum);
            if (ret != 0) {
                tempBattleScene = copyTempBattleScene;
                return ret;
            }
        }

        // 返回客户端
        XiuXianProto.XiuXianBattleOpenSkillRespMsg.Builder resp = XiuXianProto.XiuXianBattleOpenSkillRespMsg.newBuilder();
        resp.setRet(0);
        // 添加战斗结果
        for (XiuXianBattleResult battleRes : tempBattleScene.getResultMap().values()) {
            resp.addBattleResultList(XiuXianPb.parseBattleEventResultInfoTemp(battleRes));
        }
        player.sendPacket(ClientProtocol.U_XIU_XIAN_BATTLE_OPEN_SKILL, resp);
        return 0;
    }
    /**
     * 事件奖励领取（自动打理，仙力大于推荐仙力）
     * param optionNum: 选项，0默认，1开始选择
     */
    public int eventAwardAutoGet(int activityId, int missionId, int x, int y, int optionNum) {
        // 检测活动参数
        int checkRet = checkActivityData(activityId);
        if(checkRet != 0) {
            return checkRet;
        }
        XiuXianConfig config = XiuXianMgr.getConfig();

        XiuXianMissionConfig paramMissionCfg = config.getMissionConfigMap().get(missionId);
        if (null == paramMissionCfg) {
            return GameErrorCode.E_XIU_XIAN_PARAM_ERROR;
        }
        // 当前地图数据
        XiuXianMissionData missionData = missionMap.get(missionId);
        if (null == missionData ) {
            return GameErrorCode.E_XIU_XIAN_PARAM_ERROR;
        }
        if (missionData.getIsFinish()) {
            return GameErrorCode.E_XIU_XIAN_MISSION_HAS_FINISH;
        }
        // 是否已经探索完成、是否可以探索
        int result = checkCanExplore(missionData.getHasExploreGridList(), x, y, paramMissionCfg);
        if (result != 0) {
            return result;
        }
        int eventId = getPositionEvent(paramMissionCfg, x, y);
        XiuXianEventConfig eventCfg = config.getEventConfigMap().get(eventId);
        if (eventId == 0 || null == eventCfg) {
            return GameErrorCode.E_XIU_XIAN_CFG_ERROR;
        }

        if(!eXiuXianType.EventType.isBattleEvent(eventCfg.getType())){
            return GameErrorCode.E_REQUEST_ARGUMENT_ERROR;
        }
        //仙力不足
        if(userData.getPowerVal() < eventCfg.getXianLi()){
            return GameErrorCode.E_XIU_XIAN_BATTLE_EVENT_FAIL;
        }

        tempBattleScene = null;

        // 获取奖励
        String rewards = PropertyHelper.parsePropertyToString(RandomWeightConfigHelper.getProperty(eventCfg.getRewards()));
        Property rewardProperty = PropertyHelper.parseStringToProperty(rewards);
        if (rewardProperty == null) {
            return GameErrorCode.E_XIU_XIAN_CFG_ERROR;
        }
        // 道具奖励（去掉非正常道具）
        Property itemProperty = new Property();
        for (Map.Entry<Integer, BigInteger> entry : rewardProperty.getGoods().entrySet()) {
            int gId = entry.getKey();
            BigInteger value = entry.getValue();
            GoodsInfo goodsInfo = GoodsMgr.getGoodsById(gId);
            if(goodsInfo != null){
                itemProperty.addProperty(gId, value);
            }
        }

        // 更新内存数据，后给奖励
        boolean isHasExists = false;
        for(XiuXianGridPositionData posData : missionData.getHasExploreGridList()) {
            if (posData.getX() == x && posData.getY() == y) {
                isHasExists = true;
                posData.setFinishStatus(eXiuXianType.GridStatus.Finish.getValue());
                userData.setUpdateOption();
                break;
            }
        }
        if (!isHasExists) {
            XiuXianGridPositionData newGridObj = new XiuXianGridPositionData(x, y, 2);
            List<XiuXianGridPositionData> hasExploreGridList = missionData.getHasExploreGridList();
            hasExploreGridList.add(newGridObj);
        }
        // 添加道具
        player.getModule(CurrencyModule.class).addCurrency(itemProperty, eLogMoneyType.XiuXianActivity, eLogMoneyType.XiuXianActivityEventAwardGet);
        userData.setUpdateOption();
        missionData.setUpdateOption();

        if (eXiuXianType.EventType.isBattleEvent(eventCfg.getType())) {
            npcEventLogic(eventCfg, missionId, x, y);
            if(tempBattleScene != null){
                Map<Integer, Integer> monsterCfgIdMap = new ConcurrentHashMap<>();

                for(XiuXianNpcConfig npcCfg : config.getNpcConfigMap().values()) {
                    if (npcCfg.getType() == eXiuXianType.MissionNpcType.Monster.getValue()) {
                        monsterCfgIdMap.put(npcCfg.getId(), npcCfg.getSmallType());
                    }
                }
                for (XiuXianBattleData battleData : tempBattleScene.getDefenseList()) {
                    if (monsterCfgIdMap.containsKey(battleData.getNpcId())) {
                        battleData.setHp(0);
                    }
                }
            }
            // 战斗事件统计行为
            npcEventBehaviorStat(paramMissionCfg.getId(), rewardProperty.getGoods());
        } else if (eXiuXianType.EventType.isTaskEvent(eventCfg.getType())) {

            // 是否已经探索接受任务 2023-01-22 14点热更
            for (XiuXianGridPositionData posData : missionData.getHasExploreGridList()) {
                if (posData.getX() == x && posData.getY() ==y && posData.getFinishStatus() == eXiuXianType.GridStatus.NoFinish.getValue()) {
                    // 已经探索(未完成事件)
                    return GameErrorCode.E_XIU_XIAN_GRID_HAS_EXPLORE;
                }
            }
            // 任务事件  记录为未完成状态
            XiuXianGridPositionData newGridObj = new XiuXianGridPositionData(x, y, eXiuXianType.GridStatus.NoFinish.getValue());
            List<XiuXianGridPositionData> hasExploreGridList = missionData.getHasExploreGridList();
            hasExploreGridList.add(newGridObj);
            missionData.setUpdateOption();

            // 任务事件，查看是否完成
            String behaviorKey = null;
            int canGetBehaviorAwardCount = -1;       // 可以领取奖励的值
            String[] paramArray = eventCfg.getEventParameter().split("\\|");
            if (eventCfg.getType() == eXiuXianType.EventType.KillMonster.getValue()) {
                if (paramArray.length != 3) {
                    return GameErrorCode.E_XIU_XIAN_CFG_ERROR;
                }
                int behaviorParam = Integer.parseInt(paramArray[0]);
                canGetBehaviorAwardCount = Integer.parseInt(paramArray[1]);
                behaviorKey = getBehaviorKey(missionId, eXiuXianType.MissionBehaviorType.KillMonster.getValue(), behaviorParam);
            } else if (eventCfg.getType() == eXiuXianType.EventType.GetItem.getValue()) {
                if (paramArray.length != 3) {
                    return GameErrorCode.E_XIU_XIAN_CFG_ERROR;
                }
                int behaviorParam = Integer.parseInt(paramArray[1]);
                canGetBehaviorAwardCount = Integer.parseInt(paramArray[0]);
                behaviorKey = getBehaviorKey(missionId, eXiuXianType.MissionBehaviorType.GetItem.getValue(), behaviorParam);
            }
            XiuXianUserBehaviorData behaviorData = behaviorMap.get(behaviorKey);
            // 任务事件扣除数量
            if (behaviorData != null) {
                behaviorData.setCount(behaviorData.getCount() - canGetBehaviorAwardCount);
            }
        }

        // 返回客户端
        XiuXianProto.XiuXianEventAwardGetRespMsg.Builder resp = XiuXianProto.XiuXianEventAwardGetRespMsg.newBuilder();
        resp.setRet(0);
        //不下发内力丹
        int neiLiDan = 0;
        Property filterProperty = PropertyHelper.parseStringToProperty(rewards);
        for (Map.Entry<Integer, BigInteger> entry : filterProperty.getGoods().entrySet()) {
            int gId = entry.getKey();
            GoodsInfo goodsInfo = GoodsMgr.getGoodsById(gId);
            if(goodsInfo != null){
                if(goodsInfo.getType() == eGoodsType.XiuXian.getValue()){
                    neiLiDan = gId;
                    break;
                }
            }
        }
        if(neiLiDan > 0){
            filterProperty.removeProperty(neiLiDan);
            resp.setReward(PropertyHelper.parsePropertyToString(filterProperty));
        }else {
            resp.setReward(rewards);
        }
        // 同步本地图的行为统计数据
        if (eXiuXianType.EventType.isBattleEvent(eventCfg.getType())) {
            for (Map.Entry<String, XiuXianUserBehaviorData> entry : behaviorMap.entrySet()) {
                int tempMissionId = getMissionIdByBehaviorKey(entry.getKey());
                if (tempMissionId == paramMissionCfg.getId()) {
                    resp.addBehaviorDataList(XiuXianPb.parseMissionBehaviorTemp(entry.getValue()));
                }
            }
        }
        resp.setMissionInfo(XiuXianPb.parseMissionInfoTemp(missionData));
        resp.addAllItem(XiuXianPb.parseXiuXianItemMsgList(userData.getItems()));
        player.sendPacket(ClientProtocol.U_XIU_XIAN_EVENT_AWARD_GET_AUTO, resp);
        // 日志
        AutoLogMgr.add(new LogXiuXianEventFinish(userData.getUserId(), userData.getActivityId(), missionId, eventId, rewards));
        return 0;
    }

    /**
     * 事件奖励领取
     * param optionNum: 选项，0默认，1开始选择
     */
    public int eventAwardGet(int activityId, int missionId, int x, int y, int optionNum) {
        // 检测活动参数
        int checkRet = checkActivityData(activityId);
        if(checkRet != 0) {
            return checkRet;
        }
        XiuXianConfig config = XiuXianMgr.getConfig();

        XiuXianMissionConfig paramMissionCfg = config.getMissionConfigMap().get(missionId);
        if (null == paramMissionCfg) {
            return GameErrorCode.E_XIU_XIAN_PARAM_ERROR;
        }
        // 当前地图数据
        XiuXianMissionData missionData = missionMap.get(missionId);
        if (null == missionData ) {
            return GameErrorCode.E_XIU_XIAN_PARAM_ERROR;
        }
        if (missionData.getIsFinish()) {
            return GameErrorCode.E_XIU_XIAN_MISSION_HAS_FINISH;
        }
        // 是否已经探索完成、是否可以探索
        int result = checkCanExplore(missionData.getHasExploreGridList(), x, y, paramMissionCfg);
        if (result != 0) {
            return result;
        }
        int eventId = getPositionEvent(paramMissionCfg, x, y);
        XiuXianEventConfig eventCfg = config.getEventConfigMap().get(eventId);
        if (eventId == 0 || null == eventCfg) {
            return GameErrorCode.E_XIU_XIAN_CFG_ERROR;
        }

        XiuXianUserBehaviorData behaviorData = null;
        int canGetBehaviorAwardCount = -1;       // 可以领取奖励的值
        // 获取奖励
        String rewards;
        if (eXiuXianType.EventType.isBattleEvent(eventCfg.getType())) {
            // 查看战斗结果
            if (tempBattleScene == null) {
                return GameErrorCode.E_XIU_XIAN_BATTLE_DATA_ERROR;
            }
            rewards = tempBattleScene.getReward(missionId, x, y);
            if (rewards == null) {
                // 重新战斗一次
                XiuXianBattleScene battleScene = npcEventLogic(eventCfg, missionId, x, y);
                if (battleScene == null) {
                    return GameErrorCode.E_XIU_XIAN_BATTLE_DATA_ERROR;
                }
                rewards = tempBattleScene.getReward(missionId, x, y);
            }
            // 未胜利
            if (StringUtils.isNullOrEmpty(rewards)) {
                return GameErrorCode.E_XIU_XIAN_BATTLE_EVENT_FAIL;
            }
            //说是有配置宝箱
//            Property tempProperty = PropertyHelper.parseStringToProperty(rewards);
//            Property resultProperty = new Property();
//            for (Map.Entry<Integer, BigInteger> entry : tempProperty.getGoods().entrySet()) {
//                int item = entry.getKey();
//                if(GoodsBagMgr.isGoodsBag(item)){
//                    OpenGoodsBagResult openGoodsBagResult = GoodsBagMgr.getRandomGoods(item);
//                    resultProperty.addProperty(openGoodsBagResult.getReward());
//                }else {
//                    resultProperty.addProperty(item, entry.getValue());
//                }
//            }
//            rewards = PropertyHelper.parsePropertyToString(resultProperty);
        } else if (eventCfg.getType() == eXiuXianType.EventType.Select.getValue()) {
            String[] rewardArray = eventCfg.getRewards().split("\\|");
            // TODO 兼容客户端传错
            if (optionNum > rewardArray.length || optionNum < 0) {
                optionNum = 1;
            }
            rewards = rewardArray[optionNum -1];
        } else if (eventCfg.getType() == eXiuXianType.EventType.Welfare.getValue()) {
//            String[] rewardArray = eventCfg.getRewards().split("\\|");
//            rewards = rewardArray[0];
//            if (rewardArray.length > 1) {
//                // 检测额外奖励
//                if (checkWelfareExtraReward(eventCfg)) {
//                    rewards = rewardArray[0] + ";" + rewardArray[1];
//                }
//            }
            rewards = PropertyHelper.parsePropertyToString(RandomWeightConfigHelper.getProperty(eventCfg.getRewards()));
        } else if (eXiuXianType.EventType.isTaskEvent(eventCfg.getType())) {
            // 任务事件，查看是否完成
            String behaviorKey = null;
            String[] paramArray = eventCfg.getEventParameter().split("\\|");
            if (eventCfg.getType() == eXiuXianType.EventType.KillMonster.getValue()) {
                if (paramArray.length != 3) {
                    return GameErrorCode.E_XIU_XIAN_CFG_ERROR;
                }
                int behaviorParam = Integer.parseInt(paramArray[0]);
                canGetBehaviorAwardCount = Integer.parseInt(paramArray[1]);
                behaviorKey = getBehaviorKey(missionId, eXiuXianType.MissionBehaviorType.KillMonster.getValue(), behaviorParam);
            } else if (eventCfg.getType() == eXiuXianType.EventType.GetItem.getValue()) {
                if (paramArray.length != 3) {
                    return GameErrorCode.E_XIU_XIAN_CFG_ERROR;
                }
                int behaviorParam = Integer.parseInt(paramArray[1]);
                canGetBehaviorAwardCount = Integer.parseInt(paramArray[0]);
                behaviorKey = getBehaviorKey(missionId, eXiuXianType.MissionBehaviorType.GetItem.getValue(), behaviorParam);
            }
            behaviorData = behaviorMap.get(behaviorKey);
            if (canGetBehaviorAwardCount == -1 || behaviorData.getCount() < canGetBehaviorAwardCount) {
                return GameErrorCode.E_XIU_XIAN_TASK_EVENT_LIMIT;
            }
            rewards = PropertyHelper.parsePropertyToString(RandomWeightConfigHelper.getProperty(eventCfg.getRewards()));
        } else {
            return GameErrorCode.E_XIU_XIAN_CFG_ERROR;
        }
        // 奖励道具（包含非正常道具）
        Property rewardProperty = PropertyHelper.parseStringToProperty(rewards);
        if (rewardProperty == null) {
            return GameErrorCode.E_XIU_XIAN_CFG_ERROR;
        }
        // 道具奖励（去掉非正常道具）
        Property itemProperty = new Property();
        for (Map.Entry<Integer, BigInteger> entry : rewardProperty.getGoods().entrySet()) {
            int gId = entry.getKey();
            BigInteger value = entry.getValue();
            GoodsInfo goodsInfo = GoodsMgr.getGoodsById(gId);
            if(goodsInfo != null){
                itemProperty.addProperty(gId, value);
            }
        }

        // 更新内存数据，后给奖励
        boolean isHasExists = false;
        for(XiuXianGridPositionData posData : missionData.getHasExploreGridList()) {
            if (posData.getX() == x && posData.getY() == y) {
                isHasExists = true;
                posData.setFinishStatus(eXiuXianType.GridStatus.Finish.getValue());
                userData.setUpdateOption();
                break;
            }
        }
        if (!isHasExists) {
            XiuXianGridPositionData newGridObj = new XiuXianGridPositionData(x, y, 2);
            List<XiuXianGridPositionData> hasExploreGridList = missionData.getHasExploreGridList();
            hasExploreGridList.add(newGridObj);
        }
        // 添加道具
        player.getModule(CurrencyModule.class).addCurrency(itemProperty, eLogMoneyType.XiuXianActivity, eLogMoneyType.XiuXianActivityEventAwardGet);
        userData.setUpdateOption();
        missionData.setUpdateOption();

        if (eXiuXianType.EventType.isBattleEvent(eventCfg.getType())) {
            // 战斗事件统计行为
            npcEventBehaviorStat(paramMissionCfg.getId(), rewardProperty.getGoods());
        } else if (eXiuXianType.EventType.isTaskEvent(eventCfg.getType())) {
            // 任务事件扣除数量
            if (behaviorData != null) {
                behaviorData.setCount(behaviorData.getCount() - canGetBehaviorAwardCount);
            }
        }

        // 返回客户端
        XiuXianProto.XiuXianEventAwardGetRespMsg.Builder resp = XiuXianProto.XiuXianEventAwardGetRespMsg.newBuilder();
        resp.setRet(0);
        //不下发内力丹
        int neiLiDan = 0;
        Property filterProperty = PropertyHelper.parseStringToProperty(rewards);
        for (Map.Entry<Integer, BigInteger> entry : filterProperty.getGoods().entrySet()) {
            int gId = entry.getKey();
            GoodsInfo goodsInfo = GoodsMgr.getGoodsById(gId);
            if(goodsInfo != null){
                if(goodsInfo.getType() == eGoodsType.XiuXian.getValue()){
                    neiLiDan = gId;
                    break;
                }
            }
        }
        if(neiLiDan > 0){
            filterProperty.removeProperty(neiLiDan);
            resp.setReward(PropertyHelper.parsePropertyToString(filterProperty));
        }else {
            resp.setReward(rewards);
        }
        // 同步本地图的行为统计数据
        if (eXiuXianType.EventType.isBattleEvent(eventCfg.getType())) {
            for (Map.Entry<String, XiuXianUserBehaviorData> entry : behaviorMap.entrySet()) {
                int tempMissionId = getMissionIdByBehaviorKey(entry.getKey());
                if (tempMissionId == paramMissionCfg.getId()) {
                    resp.addBehaviorDataList(XiuXianPb.parseMissionBehaviorTemp(entry.getValue()));
                }
            }
        }
        resp.setMissionInfo(XiuXianPb.parseMissionInfoTemp(missionData));
        resp.addAllItem(XiuXianPb.parseXiuXianItemMsgList(userData.getItems()));
        player.sendPacket(ClientProtocol.U_XIU_XIAN_EVENT_AWARD_GET, resp);
        // 日志
        AutoLogMgr.add(new LogXiuXianEventFinish(userData.getUserId(), userData.getActivityId(), missionId, eventId, rewards));
        return 0;
    }

    /**
     * 历练地图进度奖励领取
     * subsectionVal: 进度值，目前只有完成奖励，客户端传1上来，服务端判断有值就是已经领取
     */
    public int subsectionGet(int activityId, int missionId, int subsectionVal) {
        // 检测活动参数
//        int checkRet = checkActivityData(activityId);
//        if(checkRet != 0) {
//            return checkRet;
//        }
//        XiuXianConfig config = XiuXianMgr.getConfig();
        // 没有玩家活动数据
        if(userData == null){
            return GameErrorCode.E_ACTIVITY_OVER_TIME;
        }
        // 没有活动配置
        XiuXianConfig config = XiuXianMgr.getConfig();
        if(config == null){
            return GameErrorCode.E_ACTIVITY_OVER_TIME;
        }
        // 活动是否同一个、是否在活动中
        ActivityInfo activityInfo = config.getActivityInfo();
        if(activityInfo == null || activityId != activityInfo.getActivityId()
                || !ActivityHelper.activityInShowTime(activityInfo)) {
            return GameErrorCode.E_ACTIVITY_OVER_TIME;
        }
        
        XiuXianMissionConfig curMissionCfg = config.getMissionConfigMap().get(missionId);
        if (null == curMissionCfg) {
            return GameErrorCode.E_XIU_XIAN_PARAM_ERROR;
        }
        // 当前地图数据
        XiuXianMissionData missionData = missionMap.get(curMissionCfg.getId());
        if (null == missionData) {
            return GameErrorCode.E_XIU_XIAN_PARAM_ERROR;
        }
        // 检测是是否已经完成
        if (!missionData.getIsFinish()) {
            return GameErrorCode.E_XIU_XIAN_SUBSECTION_LIMIT;
        }
        // 检测是否已经领取
        if (missionData.getSubsectionGetList().size() > 0) {
            return GameErrorCode.E_XIU_XIAN_SUBSECTION_GET;
        }

        String rewardStr = curMissionCfg.getSubsectionRewards();
        // 更新内存数据
        List<Integer> subsectionList = missionData.getSubsectionGetList();
        subsectionList.add(subsectionVal);
        // 添加奖励
        Property rewardProperty = PropertyHelper.parseStringToProperty(rewardStr);
        player.getModule(CurrencyModule.class).addCurrency(rewardProperty, eLogMoneyType.XiuXianActivity, eLogMoneyType.XiuXianActivitySubsectionAwardGet);
        userData.setUpdateOption();
        missionData.setUpdateOption();

        // 返回客户端
        XiuXianProto.XiuXianSubsectionGetRespMsg.Builder builder = XiuXianProto.XiuXianSubsectionGetRespMsg.newBuilder();
        builder.setRet(0);
        builder.setReward(rewardStr);
        builder.setMissionInfo(XiuXianPb.parseMissionInfoTemp(missionData));
        builder.addAllItem(XiuXianPb.parseXiuXianItemMsgList(userData.getItems()));
        player.sendPacket(Protocol.U_XIU_XIAN_SUBSECTION_GET, builder);
        // 日志
        AutoLogMgr.add(new LogXiuXianSubsectionReward(userData.getUserId(), userData.getActivityId(), curMissionCfg.getId(), subsectionVal, rewardStr));
        return 0;
    }
    /**
     * 进入历练地图
     */
    public int practiceMenuEnter(int activityId) {
        // 检测活动参数
        int checkRet = checkActivityData(activityId);
        if(checkRet != 0) {
            return checkRet;
        }
        // 发到跨服拿数据
        XiuXianProto.CrossXiuXianEnterPracticeReqMsg.Builder builder = XiuXianProto.CrossXiuXianEnterPracticeReqMsg.newBuilder();
        builder.setActivityId(activityId);
        player.sendPacket(CrossProtocol.C_CROSS_XIU_XIAN_ENTER_PRACTICE, builder);
        return 0;
    }
    /**
     * 离开历练地图
     */
    public void practiceMenuLeave(int activityId) {
        // 检测活动参数
        int checkRet = checkActivityData(activityId);
        if(checkRet != 0) {
            return;
        }
        // 发送到跨服
        XiuXianProto.CrossXiuXianLeavePracticeReqMsg.Builder builder = XiuXianProto.CrossXiuXianLeavePracticeReqMsg.newBuilder();
        builder.setActivityId(activityId);
        player.sendPacket(CrossProtocol.C_CROSS_XIU_XIAN_LEAVE_PRACTICE, builder);

        return;
    }
    /**
     * 进入二级界面
     */
    public int secondMenuEnter(int activityId) {
        // 检测活动参数
        int checkRet = checkActivityData(activityId);
        if(checkRet != 0) {
            return checkRet;
        }

        // 旧修为值
        long oldPracticeValue = userData.getPracticeVal();
        long oldLastMeditateTime = userData.getLastMeditateTime();
        // 计算修为
        calcPracticeSpeedNew();

        // 返回客户端
        XiuXianProto.XiuXianEnterSecondMenuRespMsg.Builder builder = XiuXianProto.XiuXianEnterSecondMenuRespMsg.newBuilder();
        builder.setRet(0);
        builder.setOfflineTime(userData.getLastMeditateTime() - oldLastMeditateTime);
        builder.setAddPracticeValue(userData.getPracticeVal() - oldPracticeValue);
        player.sendPacket(ClientProtocol.U_XIU_XIAN_ENTER_SECOND_MENU, builder);
        return 0;
    }
    /**
     * 离开二级界面
     */
    public void secondMenuLeave(int activityId) {
        // 检测活动参数
        int checkRet = checkActivityData(activityId);
        if(checkRet != 0) {
            return;
        }
        // 计算修为
        calcPracticeSpeedNew();
    }
    /**
     * 进入宗门灵峰
     */
    public int enterSectMount(int activityId) {
        // 检测活动参数
        int checkRet = checkActivityData(activityId);
        if(checkRet != 0) {
            return checkRet;
        }
        // 发送到跨服
        XiuXianProto.CrossXiuXianEnterSectMountReqMsg.Builder builder = XiuXianProto.CrossXiuXianEnterSectMountReqMsg.newBuilder();
        builder.setActivityId(activityId);
        player.sendPacket(CrossProtocol.C_CROSS_XIU_XIAN_ENTER_SECT_MOUNT, builder);
        return 0;
    }
    /**
     * 进入其他灵峰房间
     */
    public int enterOtherSectMount(int activityId, int mountId, int roomId) {
        // 检测活动参数
        int checkRet = checkActivityData(activityId);
        if(checkRet != 0) {
            return checkRet;
        }
        // 发送到跨服
        XiuXianProto.CrossXiuXianEnterOtherSectMountReqMsg.Builder builder = XiuXianProto.CrossXiuXianEnterOtherSectMountReqMsg.newBuilder();
        builder.setActivityId(activityId);
        builder.setMountId(mountId);
        builder.setRoomId(roomId);
        player.sendPacket(CrossProtocol.C_CROSS_XIU_XIAN_ENTER_OTHER_SECT_MOUNT, builder);
        return 0;
    }

    /**
     * 离开宗门灵峰
     */
    public int leaveSectMount(int activityId, int mountId, int roomId) {
        // 检测活动参数
        int checkRet = checkActivityData(activityId);
        if(checkRet != 0) {
            return checkRet;
        }
        // 发送到跨服
        XiuXianProto.CrossXiuXianLeaveSectMountReqMsg.Builder builder = XiuXianProto.CrossXiuXianLeaveSectMountReqMsg.newBuilder();
        builder.setActivityId(activityId);
        builder.setMountId(mountId);
        builder.setRoomId(roomId);
        player.sendPacket(CrossProtocol.C_CROSS_XIU_XIAN_LEAVE_SECT_MOUNT, builder);
        return 0;
    }

    /**
     * 获取灵峰信息
     */
    public int getMountInfo(int activityId) {
        // 检测活动参数
        int checkRet = checkActivityData(activityId);
        if(checkRet != 0) {
            return checkRet;
        }
        // 发送到跨服
        XiuXianProto.CrossXiuXianGetMountInfoReqMsg.Builder builder = XiuXianProto.CrossXiuXianGetMountInfoReqMsg.newBuilder();
        builder.setActivityId(activityId);
        player.sendPacket(CrossProtocol.C_CROSS_XIU_XIAN_GET_MOUNT_INFO, builder);
        return 0;
    }

    /**
     * 获取宗门仙力排行
     */
    public int getCampPowerRank(int activityId) {
        // 检测活动参数
        int checkRet = checkActivityData(activityId);
        if(checkRet != 0) {
            return checkRet;
        }
        // 发送到跨服
        XiuXianProto.CrossXiuXianPowerRankListReqMsg.Builder builder = XiuXianProto.CrossXiuXianPowerRankListReqMsg.newBuilder();
        builder.setActivityId(activityId);
        player.sendPacket(CrossProtocol.C_CROSS_XIU_XIAN_GET_POWER_RANK, builder);
        return 0;
    }
    /**
     * 获取宗门体力贡献排行
     */
    public int getCampEnergyRank(int activityId) {
        // 检测活动参数
        int checkRet = checkActivityData(activityId);
        if(checkRet != 0) {
            return checkRet;
        }
        // 发送到跨服
        XiuXianProto.CrossXiuXianEnergyRankListReqMsg.Builder builder = XiuXianProto.CrossXiuXianEnergyRankListReqMsg.newBuilder();
        builder.setActivityId(activityId);
        player.sendPacket(CrossProtocol.C_CROSS_XIU_XIAN_GET_ENERGY_RANK, builder);
        return 0;
    }

    /**
     * 查看其他玩家信息
     */
    public int getOtherUserInfo(int activityId, long otherUserId, long otherServerId) {
        // 检测活动参数
        int checkRet = checkActivityData(activityId);
        if(checkRet != 0) {
            return checkRet;
        }
        // 发到跨服拿数据
        XiuXianProto.CrossXiuXianGetOtherUserInfoReqMsg.Builder builder = XiuXianProto.CrossXiuXianGetOtherUserInfoReqMsg.newBuilder();
        builder.setActivityId(activityId);
        builder.setServerId(otherServerId);
        builder.setUserId(otherUserId);
        player.sendPacket(CrossProtocol.C_CROSS_XIU_XIAN_GET_OTHER_USER_INFO, builder);
        return 0;
    }

    /**
     * 跨服查看其他玩家信息
     */
    public static int getOtherInfoFromCross(XiuXianUserData userData, int activityId, long getUserId, long getServerId) {
        XiuXianProto.XiuXianPveGetOtherUserInfoRespMsg.Builder clientMsg = XiuXianProto.XiuXianPveGetOtherUserInfoRespMsg.newBuilder();
        clientMsg.setRet(0);
        XiuXianProto.XiuXianPveOtherUserTemp.Builder otherUserTemp = XiuXianProto.XiuXianPveOtherUserTemp.newBuilder();
        otherUserTemp.setPowerVal(userData.getPowerVal());
        otherUserTemp.setUserMountInfo(CrossXiuXianPb.parsePveSampleTemp(
                UserMgr.getUserBaseInfo(userData.getUserId(), GameServer.getInstance().getServerId()), userData)
        );
        if (null != userData.getEquipmentMap()) {
            for (XiuXianEquipmentData data : userData.getEquipmentMap().values()) {
                XiuXianProto.EquipmentInfoTemp.Builder parseEquipmentInfo = XiuXianPb.parseEquipmentInfoTemp(data);
                if(parseEquipmentInfo != null) {
                    otherUserTemp.addEquipmentList(parseEquipmentInfo);
                }
            }
        }
        for (Map.Entry<Integer, Long> entry : userData.getProperty().getAttrMap().entrySet()) {
            otherUserTemp.addAttrList(XiuXianPb.parseXiuXianAttrInfoTemp(entry.getKey(), entry.getValue()));
        }
        clientMsg.setOtherUserInfo(otherUserTemp);
        clientMsg.setUser(PlayerPb.parsePlayerBaseTempMsg(UserMgr.getUserInfo(userData.getUserId())));

        // 回复跨服
        XiuXianProto.XiuXianGetOtherInfoFromCrossRespMsg.Builder builder = XiuXianProto.XiuXianGetOtherInfoFromCrossRespMsg.newBuilder();
        builder.setUserId(getUserId);
        builder.setServerId(getServerId);
        builder.setRespMsg(clientMsg);
        builder.setActivityId(activityId);
        YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.C_CROSS_XIU_XIAN_GET_OTHER_INFO_RESP, builder);
        GamePlayerMgr.sendPacket(userData.getUserId(), pbMsg);
        return 0;
    }
    /**
     * 检测福利事件额外奖励是否完成
     */
    private boolean checkWelfareExtraReward(XiuXianEventConfig eventCfg) {
        boolean isFinish = false;
        if (null == eventCfg) {
            return isFinish;
        }
        String[] eventParamArray = eventCfg.getEventParameter().split("\\|");
        if (eventParamArray.length != 2) {
            return isFinish;
        }
        int attrId = Integer.parseInt(eventParamArray[0]);
        int needAttrVal =Integer.parseInt(eventParamArray[1]);
        long curAttrVal = userData.getProperty().getAttrMap().getOrDefault(attrId, 0L);
        if (curAttrVal >= needAttrVal) {
            isFinish = true;
        }
        return isFinish;
    }
    /**
     * 随机属性 3#3=180;200|4=180;200|5=720;800|6=180;200
     */
    private Map<Integer, Long> randomAdvanceAttr(String attributeStr) {
        Map<Integer, Long> attrAdvanceMap = new ConcurrentHashMap<>();

        String[] parseArray = attributeStr.split("#");

        int randomNum = Integer.valueOf(parseArray[0]);         // 随机数量
        // 属性列表
        List<String> attrStrList = StringUtils.stringToStringList(parseArray[1], "\\|");
        for (int i = 0; i < randomNum; i++) {
            // 随机下标
            int randomIndex = randomHelper.next(attrStrList.size());

            String[] paramArray = attrStrList.get(randomIndex).split("=");
            List<Integer> valueList = StringUtils.stringToIntegerList(paramArray[1], ";");
            long value = randomHelper.next(valueList.get(0), valueList.get(1));
            attrAdvanceMap.put(Integer.valueOf(paramArray[0]), value);
            // 删除随机过的
            attrStrList.remove(randomIndex);
        }
        return attrAdvanceMap;
    }
    /**
     * 是否有本命法宝
     */
    private boolean isHasExclusive() {
        XiuXianConfig config = XiuXianMgr.getConfig();
        for (XiuXianEquipmentData equipmentData : userData.getEquipmentMap().values()) {
            XiuXianEquipmentConfig equipmentCfg = config.getEquipmentConfigMap().get(equipmentData.getEquipmentId());
            // 本命法宝
            if (equipmentCfg.getType() == eXiuXianType.EquipmentType.Exclusive.getValue()) {
                return true;
            }
        }
        return false;
    }

    public void addXiuXianGoods(int itemId, BigInteger count) {
        Property property = new Property();
        property.addProperty(itemId, count);
        addItem(userData, property);
    }

    /**
     * 增加机缘点
     */
    public void addXiuXianJiYuanDian(BigInteger count) {
        XiuXianConfig config = XiuXianMgr.getConfig();
        if (config == null || !ActivityMgr.activityInShowTime(config.getActivityInfo())) {
            return;
        }
        if (userData == null) {
            return;
        }
        userData.setLuckPoint(userData.getLuckPoint() + count.intValue());
        // 同步下数据
        syncUserData();
    }

    private void addItem(XiuXianUserData userData, Property change) {
        userData.getItems().addProperty(change);
        userData.setUpdateOption();
    }
    /**
     * 扣除道具
     */
    private boolean removeItem(XiuXianUserData userData, Property change) {
        Property items = userData.getItems();
        // 看看够不够
        if (!checkItemEnough(userData, change)) {
            return false;
        }
        // 扣道具
        for (Map.Entry<Integer, BigInteger> entry : change.getGoods().entrySet()) {
            Integer itemId = entry.getKey();
            BigInteger count = entry.getValue();
            items.removeProperty(itemId, count);
        }
        userData.setUpdateOption();
        return true;
    }
    /**
     * 检测道具是否足够
     */
    private boolean checkItemEnough(XiuXianUserData userData, Property change) {
        Property items = userData.getItems();
        // 看看够不够
        for (Map.Entry<Integer, BigInteger> entry : change.getGoods().entrySet()) {
            Integer itemId = entry.getKey();
            BigInteger count = entry.getValue();
            if (items.getCountByGoodsId(itemId).compareTo(count) < 0) {
                return false;
            }
        }
        return true;
    }
}
